From bbcdf6815d0de06d1775e677ebd3fe40d23a6622 Mon Sep 17 00:00:00 2001 From: Zachary Harrold Date: Tue, 27 Feb 2024 17:03:34 +1100 Subject: [PATCH] `bevy_color`: Added Color Conversion Mermaid Diagram (#12147) Shows relationships between color spaces and explains what files should contain which conversions. # Objective - Provide documentation for maintainers and users on how color space conversion is implemented. ## Solution - Created a mermaid diagram documenting the relationships between various color spaces. This diagram also includes links to defining articles, and edges include links to conversion formulae. - Added a `conversion.md` document which is included in the documentation of each of the color spaces. This ensures it is readily visible in all relevant contexts. ## Notes The diagram is in the Mermaid (`.mmd`) format, and must be converted into an SVG file (or other image format) prior to use in Rust documentation. I've included a link to [mermaid.live](https://mermaid.live) as an option for doing such conversion in an appropriate README. Below is a screenshot of the documentation added. ![Capture](https://github.com/bevyengine/bevy/assets/2217286/370a65f2-6dd4-4af7-a99b-3763832d1b8a) --- crates/bevy_color/docs/conversion.md | 16 ++++++++++++++ crates/bevy_color/docs/diagrams/README.md | 3 +++ .../bevy_color/docs/diagrams/model_graph.mmd | 22 +++++++++++++++++++ .../bevy_color/docs/diagrams/model_graph.svg | 1 + crates/bevy_color/src/color.rs | 4 ++++ crates/bevy_color/src/hsla.rs | 4 ++++ crates/bevy_color/src/hsva.rs | 4 ++++ crates/bevy_color/src/hwba.rs | 4 ++++ crates/bevy_color/src/laba.rs | 4 ++++ crates/bevy_color/src/lcha.rs | 4 ++++ crates/bevy_color/src/lib.rs | 9 ++++---- crates/bevy_color/src/linear_rgba.rs | 4 ++++ crates/bevy_color/src/oklaba.rs | 4 ++++ crates/bevy_color/src/srgba.rs | 4 ++++ crates/bevy_color/src/xyza.rs | 4 ++++ 15 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 crates/bevy_color/docs/conversion.md create mode 100644 crates/bevy_color/docs/diagrams/README.md create mode 100644 crates/bevy_color/docs/diagrams/model_graph.mmd create mode 100644 crates/bevy_color/docs/diagrams/model_graph.svg diff --git a/crates/bevy_color/docs/conversion.md b/crates/bevy_color/docs/conversion.md new file mode 100644 index 0000000000..096044e52f --- /dev/null +++ b/crates/bevy_color/docs/conversion.md @@ -0,0 +1,16 @@ +# Conversion + +Conversion between the various color spaces is achieved using Rust's native [From] trait. Because certain color spaces are defined by their transformation to and from another space, these [From] implementations reflect that set of definitions. + +```rust +# use bevy_color::{Srgba, LinearRgba}; +let color = Srgba::rgb(0.5, 0.5, 0.5); + +// Using From explicitly +let linear_color = LinearRgba::from(color); + +// Using Into +let linear_color: LinearRgba = color.into(); +``` + +For example, the [sRGB](crate::Srgba) space is defined by its relationship with [Linear RGB](crate::LinearRgba), and [HWB](crate::Hwba) by its with [sRGB](crate::Srgba). As such, it is the responsibility of [sRGB](crate::Srgba) to provide [From] implementations for [Linear RGB](crate::LinearRgba), and [HWB](crate::Hwba) for [sRGB](crate::Srgba). To then provide conversion between [Linear RGB](crate::LinearRgba) and [HWB](crate::Hwba) directly, [HWB](crate::Hwba) is responsible for implementing these conversions, delegating to [sRGB](crate::Srgba) as an intermediatory. This ensures that all conversions take the shortest path between any two spaces, and limit the proliferation of domain specific knowledge for each color space to their respective definitions. diff --git a/crates/bevy_color/docs/diagrams/README.md b/crates/bevy_color/docs/diagrams/README.md new file mode 100644 index 0000000000..fc6bb9f9dd --- /dev/null +++ b/crates/bevy_color/docs/diagrams/README.md @@ -0,0 +1,3 @@ +# Creating Mermaid Diagrams + +Mermaid diagrams (`.mmd` files) can be converted to SVG using various tools. The simplest to work with is [mermaid.live](https://mermaid.live/), which is a HTML web app. When editing `.mmd` files, make sure to regenerate the associated SVGs. diff --git a/crates/bevy_color/docs/diagrams/model_graph.mmd b/crates/bevy_color/docs/diagrams/model_graph.mmd new file mode 100644 index 0000000000..d7fc5e1b24 --- /dev/null +++ b/crates/bevy_color/docs/diagrams/model_graph.mmd @@ -0,0 +1,22 @@ +%%{ init: { 'theme': 'dark', 'flowchart': { 'curve': 'stepAfter', 'padding': 30 }, 'themeCSS': '.label foreignObject { overflow: visible; }' } }%% +flowchart LR + lRGB(Linear
sRGB
) + Oklab(Oklab) + Oklch(Oklch) + XYZ(XYZ) + Lab(Lab) + Lch(Lch) + sRGB(sRGB) + HWB(HWB) + HSV(HSV) + HSL(HSL) + GPU <--> lRGB + lRGB <--Conversion--> Oklab + Oklab <--Conversion--> Oklch + lRGB <--Conversion--> XYZ + XYZ <--Conversion--> Lab + Lab <--Conversion--> Lch + lRGB <--Conversion--> sRGB + sRGB <--Conversion--> HWB + HWB <--Conversion--> HSV + HSV <--Conversion--> HSL \ No newline at end of file diff --git a/crates/bevy_color/docs/diagrams/model_graph.svg b/crates/bevy_color/docs/diagrams/model_graph.svg new file mode 100644 index 0000000000..5c1d3dceb7 --- /dev/null +++ b/crates/bevy_color/docs/diagrams/model_graph.svg @@ -0,0 +1 @@ +
GPU
\ No newline at end of file diff --git a/crates/bevy_color/src/color.rs b/crates/bevy_color/src/color.rs index d1d24e2833..665a2ee720 100644 --- a/crates/bevy_color/src/color.rs +++ b/crates/bevy_color/src/color.rs @@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize}; /// /// This is useful when you need to store a color in a data structure that can't be generic over /// the color type. +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub enum Color { diff --git a/crates/bevy_color/src/hsla.rs b/crates/bevy_color/src/hsla.rs index 3739c4b144..b0774b1322 100644 --- a/crates/bevy_color/src/hsla.rs +++ b/crates/bevy_color/src/hsla.rs @@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize}; /// Color in Hue-Saturation-Lightness (HSL) color space with alpha. /// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HSL_and_HSV). +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Hsla { diff --git a/crates/bevy_color/src/hsva.rs b/crates/bevy_color/src/hsva.rs index 0583491e68..f671981ddc 100644 --- a/crates/bevy_color/src/hsva.rs +++ b/crates/bevy_color/src/hsva.rs @@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize}; /// Color in Hue-Saturation-Value (HSV) color space with alpha. /// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HSL_and_HSV). +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Hsva { diff --git a/crates/bevy_color/src/hwba.rs b/crates/bevy_color/src/hwba.rs index 5105e59d6a..744acd865b 100644 --- a/crates/bevy_color/src/hwba.rs +++ b/crates/bevy_color/src/hwba.rs @@ -8,6 +8,10 @@ use serde::{Deserialize, Serialize}; /// Color in Hue-Whiteness-Blackness (HWB) color space with alpha. /// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HWB_color_model). +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Hwba { diff --git a/crates/bevy_color/src/laba.rs b/crates/bevy_color/src/laba.rs index 4b4714a3a8..43b4556359 100644 --- a/crates/bevy_color/src/laba.rs +++ b/crates/bevy_color/src/laba.rs @@ -5,6 +5,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use serde::{Deserialize, Serialize}; /// Color in LAB color space, with alpha +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Laba { diff --git a/crates/bevy_color/src/lcha.rs b/crates/bevy_color/src/lcha.rs index 2a01147a68..4e9192146b 100644 --- a/crates/bevy_color/src/lcha.rs +++ b/crates/bevy_color/src/lcha.rs @@ -3,6 +3,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use serde::{Deserialize, Serialize}; /// Color in LCH color space, with alpha +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Lcha { diff --git a/crates/bevy_color/src/lib.rs b/crates/bevy_color/src/lib.rs index a90c2fd627..0c1dca63d1 100644 --- a/crates/bevy_color/src/lib.rs +++ b/crates/bevy_color/src/lib.rs @@ -50,11 +50,10 @@ //! //! See also the [Wikipedia article on color spaces](https://en.wikipedia.org/wiki/Color_space). //! -//! # Conversions -//! -//! Each color space can be converted to and from the others using the [`From`] trait. Not all -//! possible combinations of conversions are provided, but every color space has a conversion to -//! and from [`Srgba`] and [`LinearRgba`]. +#![doc = include_str!("../docs/conversion.md")] +//!
+#![doc = include_str!("../docs/diagrams/model_graph.svg")] +//!
//! //! # Other Utilities //! diff --git a/crates/bevy_color/src/linear_rgba.rs b/crates/bevy_color/src/linear_rgba.rs index 462c7033e6..c0aeb88dfc 100644 --- a/crates/bevy_color/src/linear_rgba.rs +++ b/crates/bevy_color/src/linear_rgba.rs @@ -5,6 +5,10 @@ use bytemuck::{Pod, Zeroable}; use serde::{Deserialize, Serialize}; /// Linear RGB color with alpha. +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] #[repr(C)] diff --git a/crates/bevy_color/src/oklaba.rs b/crates/bevy_color/src/oklaba.rs index 5913dcbfa5..d98d6ef8ba 100644 --- a/crates/bevy_color/src/oklaba.rs +++ b/crates/bevy_color/src/oklaba.rs @@ -6,6 +6,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use serde::{Deserialize, Serialize}; /// Color in Oklaba color space, with alpha +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Oklaba { diff --git a/crates/bevy_color/src/srgba.rs b/crates/bevy_color/src/srgba.rs index 696484e7ce..b2425bb36c 100644 --- a/crates/bevy_color/src/srgba.rs +++ b/crates/bevy_color/src/srgba.rs @@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; /// Non-linear standard RGB with alpha. +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Srgba { diff --git a/crates/bevy_color/src/xyza.rs b/crates/bevy_color/src/xyza.rs index 6694ee38e0..0aa8a0f5a9 100644 --- a/crates/bevy_color/src/xyza.rs +++ b/crates/bevy_color/src/xyza.rs @@ -3,6 +3,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use serde::{Deserialize, Serialize}; /// [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space) color space, also known as XYZ, with an alpha channel. +#[doc = include_str!("../docs/conversion.md")] +///
+#[doc = include_str!("../docs/diagrams/model_graph.svg")] +///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize)] pub struct Xyza {