From 11d45bba1e2b9268492a95b5bf65f9f51047bf8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?joseLu=C3=ADs?= <joseluis@andamira.net>
Date: Mon, 25 Nov 2024 20:49:33 +0100
Subject: [PATCH] refactor `rend::color`

- new trait: `ColorBase`.
- rename `COLOR` namespace to `Color`.
- remove `color_` prefix from namespace methods.
- misc. refactoring.
---
 DOCS/CHANGELOG.md                          |  3 +-
 src/rend/color/base.rs                     | 41 +++++++++++++++++++
 src/rend/color/mod.rs                      |  8 ++--
 src/rend/color/{struct.rs => namespace.rs} | 47 ++++++++--------------
 src/rend/color/trait.rs                    | 46 ---------------------
 5 files changed, 64 insertions(+), 81 deletions(-)
 create mode 100644 src/rend/color/base.rs
 rename src/rend/color/{struct.rs => namespace.rs} (55%)
 delete mode 100644 src/rend/color/trait.rs

diff --git a/DOCS/CHANGELOG.md b/DOCS/CHANGELOG.md
index 20f279e2..51286051 100644
--- a/DOCS/CHANGELOG.md
+++ b/DOCS/CHANGELOG.md
@@ -38,7 +38,7 @@ The format is based on [Keep a Changelog], and this project adheres to
 - enum variants:
   - `DataError::ElementNotFound`.
 - traits:
-  - `ExtCellOption`, `ExtOptRes`, `MemPod`, `TypeResourced`, `Unit`.
+  - `ColorBase`, `ExtCellOption`, `ExtOptRes`, `MemPod`, `TypeResourced`, `Unit`.
   - `WaveletCompressionVec`, `WaveletTransformVec`.
 - associated methods and constants for:
   - `Array`: `from_fn`, `contains_[from|to|between]`.
@@ -127,6 +127,7 @@ The format is based on [Keep a Changelog], and this project adheres to
 - structs:
   - make `data::dst` types use `MemPod` instead of `bytemuck::Pod`.
   - rename:
+    - `COLOR` to `Color`.
     - `GcdExt` to `GcdResult`.
     - `AllocMap` to `HashMap` and `AllocSet` to `HashSet`.
     - `AllocOrdMap` to `BTreeMap` and `AllocOrdSet` to `BTreeSet`.
diff --git a/src/rend/color/base.rs b/src/rend/color/base.rs
new file mode 100644
index 00000000..2fcbedb0
--- /dev/null
+++ b/src/rend/color/base.rs
@@ -0,0 +1,41 @@
+// devela::rend::color::base
+//
+//!
+//
+
+#[cfg(feature = "alloc")]
+use crate::{vec_ as vec, Vec};
+
+/// Base trait for general color data representation.
+///
+/// Provides a core interface for working with color data across different
+/// formats and models, supporting both practical and scientific applications.
+pub trait ColorBase {
+    /// The type used for color components.
+    type Component;
+
+    /// Returns the number of color components.
+    ///
+    /// For example:
+    /// - RGB returns `3`
+    /// - Spectral data may return `n`
+    fn color_component_count(&self) -> usize;
+
+    /// Writes the color components to a pre-allocated buffer.
+    ///
+    /// # Panics
+    /// Panics if the buffer size is less than `color_component_count()`.
+    // TODO: Return Error
+    fn color_components_write(&self, buffer: &mut [Self::Component]);
+
+    /// Returns a vector containing the color components.
+    #[cfg(feature = "alloc")]
+    fn color_components_vec(&self) -> Vec<Self::Component>
+    where
+        Self::Component: Default + Clone,
+    {
+        let mut buffer = vec![Self::Component::default(); self.color_component_count()];
+        self.color_components_write(&mut buffer);
+        buffer
+    }
+}
diff --git a/src/rend/color/mod.rs b/src/rend/color/mod.rs
index 2e8268da..b13e0991 100644
--- a/src/rend/color/mod.rs
+++ b/src/rend/color/mod.rs
@@ -3,14 +3,14 @@
 //! Chromatic functionality.
 //
 
+mod base;
 mod error;
-mod r#struct;
-mod r#trait;
+mod namespace;
 #[allow(unused_imports)]
-pub use {error::*, r#struct::*, r#trait::*};
+pub use {base::*, error::*, namespace::*};
 
 pub(crate) mod all {
     #[doc(inline)]
     #[allow(unused_imports)]
-    pub use super::{error::*, r#struct::*, r#trait::*};
+    pub use super::{base::*, error::*, namespace::*};
 }
diff --git a/src/rend/color/struct.rs b/src/rend/color/namespace.rs
similarity index 55%
rename from src/rend/color/struct.rs
rename to src/rend/color/namespace.rs
index 71420e3c..bdb33e74 100644
--- a/src/rend/color/struct.rs
+++ b/src/rend/color/namespace.rs
@@ -1,41 +1,28 @@
-// devela::rend::color::fns
+// devela::rend::color::namespace
 //
 //! Standalone color functions and constants.
 //
 
 #[allow(unused_imports)]
-use crate::code::{iif, paste, sf};
+use crate::code::{iif, paste, sf, CONST};
 
 #[cfg(all(_float_·, not(feature = "std")))]
 #[allow(unused_imports, reason = "!std: powf, powi")]
 use crate::num::ExtFloat;
 
-/// color namespace for constants and methods
-pub struct COLOR;
+/// Color namespace for constants and methods
+pub struct Color;
 
-sf! { macro_rules! LUMINANCE_RED   { () => { 0.212639 }; } pub(crate) use LUMINANCE_RED;   }
-sf! { macro_rules! LUMINANCE_GREEN { () => { 0.715169 }; } pub(crate) use LUMINANCE_GREEN; }
-sf! { macro_rules! LUMINANCE_BLUE  { () => { 0.072192 }; } pub(crate) use LUMINANCE_BLUE;  }
-
-impl COLOR {
-    /* constants */
-
-    /// The coefficient used for calculating the red luminance.
-    pub const LUMINANCE_RED: f32 = LUMINANCE_RED![];
-
-    /// The coefficient used for calculating the green luminance.
-    pub const LUMINANCE_GREEN: f32 = LUMINANCE_GREEN![];
-
-    /// The coefficient used for calculating the blue luminance.
-    pub const LUMINANCE_BLUE: f32 = LUMINANCE_BLUE![];
-}
-
-// $t:   the floating-point primitive
-// $cap: the capability feature that enables the given implementation. E.g "_f32".
+#[doc = crate::doc_private!()]
+///
+///
+/// # Args
+/// $t:   the floating-point primitive
+/// $cap: the capability feature that enables the given implementation. E.g "_f32".
 macro_rules! color_gamma_fns {
     ($($t:ty : $cap:literal),+) => { $( color_gamma_fns![@$t:$cap]; )+ };
     (@$t:ty : $cap:literal) => { paste! {
-        impl COLOR {
+        impl Color {
             #[doc = "Applies the `gamma` *(γ)* to a linear `" $t "` channel to make it non-linear."]
             ///
             /// # Algorithm
@@ -50,8 +37,8 @@ macro_rules! color_gamma_fns {
             /// $$
             #[cfg(any(feature = "std", feature = $cap))]
             #[cfg_attr(feature = "nightly_doc", doc(cfg(any(feature = "std", feature = $cap))))]
-            pub fn [<color_gamma_apply_ $t>](c: $t, gamma: $t) -> $t {
-                iif![c <= 0.0031308; 12.92 * c; 1.055 * c.powf(1.0 / gamma) - 0.055]
+            pub fn [<gamma_apply_ $t>](c: $t, gamma: $t) -> $t {
+                iif![c <= 0.003_130_8; 12.92 * c; 1.055 * c.powf(1.0 / gamma) - 0.055]
             }
 
             #[doc = "Removes the `gamma` *(γ)* from a non-linear `" $t "` channel to make it linear."]
@@ -59,8 +46,8 @@ macro_rules! color_gamma_fns {
             /// # Algorithm
             /// $$
             /// \begin{align}
-            /// \notag f_\text{remove}(c) = \large\begin{cases}
-            /// \Large\frac{c}{12.92},
+            /// \notag f_\text{remove}(c) = \begin{cases}
+            /// c / 12.92,
             ///   & \normalsize\text{if } c <= 0.04045 \cr
             /// \left(\Large\frac{c+0.055}{1.055} - \normalsize 0.055\right)^{\gamma},
             ///   & \normalsize \text{if } c > 0.04045 \end{cases} \cr
@@ -68,8 +55,8 @@ macro_rules! color_gamma_fns {
             /// $$
             #[cfg(any(feature = "std", feature = $cap))]
             #[cfg_attr(feature = "nightly_doc", doc(cfg(any(feature = "std", feature = $cap))))]
-            pub fn [<color_gamma_remove_ $t>](c: $t, gamma: $t) -> $t {
-                iif![c <= 0.04045; c / 12.92; ((c + 0.055) / (1.055)).powf(gamma)]
+            pub fn [<gamma_remove_ $t>](c: $t, gamma: $t) -> $t {
+                iif![c <= 0.040_45; c / 12.92; ((c + 0.055) / (1.055)).powf(gamma)]
             }
         }
     }};
diff --git a/src/rend/color/trait.rs b/src/rend/color/trait.rs
deleted file mode 100644
index 085049f0..00000000
--- a/src/rend/color/trait.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// devela::rend::color::trait
-//
-//!
-//
-
-/// Common color trait.
-pub trait Color {
-    /// The type of the inner color components.
-    type Inner: Copy + PartialEq;
-
-    /* methods */
-
-    /// Returns the red luminosity.
-    fn color_red(&self) -> Self::Inner;
-
-    /// Returns the green luminosity.
-    fn color_green(&self) -> Self::Inner;
-
-    /// Returns the blue luminosity.
-    fn color_blue(&self) -> Self::Inner;
-
-    /// Returns the alpha luminosity.
-    fn color_alpha(&self) -> Self::Inner;
-
-    /// Returns the overall luminosity.
-    //
-    // If the color is not in [`Oklab32`] or [`Oklch32`] format,
-    // it will be converted to `Oklab32` for the operation.
-    fn color_luminosity(&self) -> Self::Inner;
-
-    /// Returns the hue.
-    //
-    // If the color is not in [`Oklch32`] format
-    // it will be converted to it for the operation.
-    fn color_hue(&self) -> Self::Inner;
-
-    /* conversions */
-
-    /// Returns the 3 components, without alpha.
-    fn color_to_array3(&self) -> [Self::Inner; 3];
-
-    /// Returns the 4 components, with alpha.
-    ///
-    /// If the specific color type has no alpha the maximum value is returned.
-    fn color_to_array4(&self) -> [Self::Inner; 4];
-}