Replace 'Srgba8' with generic 'Rgba'; Add 'Component' trait; Add 'f16' and 'f128' features; Add 'to_u32' conversion destructor to 'Rgba<u8>'; Add 'from_u32' constructor to 'Rgba<u8>'; Replace 'zerocopy::FromBytes' with 'zerocopy::FromZeros' for 'Rgba'; Replace 'bytemuck::AnyBitPattern' with 'bytemuck::Zeroable' for 'Rgba'; Do not implement 'bytemuck::NoUninit' for 'Rgba'; Implement 'Display' for 'Rgba<u8>'; Implement 'Component' for 'u8', 'i8', 'u16', 'i16', 'u32', 'i32', 'u64', 'i64', 'u128', 'i128', 'f16', 'f32', 'f64', and 'f128'; Implement 'FromStr' for 'Rgba<u8>'; Add 'error' module; Add 'RgbaU8FromStrError' error type; Add tests; Rename project to *Polywave* (from *Sibgha*); Rename 'sibgha' crate to 'polywave'; Add docs; Update lints; Add readme; Add 'to_f16_lossy', 'to_f32_lossy', 'to_f64_lossy', and 'to_f128_lossy' methods to 'Component';
This commit is contained in:
parent
391857d313
commit
2517204e74
10 changed files with 441 additions and 103 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,8 +1,31 @@
|
|||
# Changelog
|
||||
|
||||
This is the changelog of [Sibgha](https://crates.io/crates/sibgha/).
|
||||
This is the changelog of [Polywave](https://crates.io/crates/polywave/).
|
||||
See `README.md` for more information.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
* Replace `Srgba8` with generic `Rgba`
|
||||
* Add `Component` trait
|
||||
* Add `f16` and `f128` features
|
||||
* Add `to_u32` conversion destructor to `Rgba<u8>`
|
||||
* Add `from_u32` constructor to `Rgba<u8>`
|
||||
* Replace `zerocopy::FromBytes` with `zerocopy::FromZeros` for `Rgba`
|
||||
* Replace `bytemuck::AnyBitPattern` with `bytemuck::Zeroable` for `Rgba`
|
||||
* Do not implement `bytemuck::NoUninit` for `Rgba`
|
||||
* Implement `Display` for `Rgba<u8>`
|
||||
* Implement `Component` for `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `f16`, `f32`, `f64`, and `f128`
|
||||
* Implement `FromStr` for `Rgba<u8>`
|
||||
* Add `error` module
|
||||
* Add `RgbaU8FromStrError` error type
|
||||
* Add tests
|
||||
* Rename project to *Polywave* (from *Sibgha*)
|
||||
* Rename `sibgha` crate to `polywave`
|
||||
* Add docs
|
||||
* Update lints
|
||||
* Add readme
|
||||
* Add `to_f16_lossy`, `to_f32_lossy`, `to_f64_lossy`, and `to_f128_lossy` methods to `Component`
|
||||
|
||||
## 0.0.0
|
||||
|
||||
* Configure lints
|
||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -7,28 +7,30 @@
|
|||
# <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
[package]
|
||||
name = "sibgha"
|
||||
version = "0.0.0"
|
||||
name = "polywave"
|
||||
version = "0.1.0"
|
||||
authors = ["Gabriel Bjørnager Jensen"]
|
||||
edition = "2021"
|
||||
rust-version = "1.82"
|
||||
description = "Vector-based colour manipulators."
|
||||
documentation = "https://docs.rs/sibgha/"
|
||||
homepage = "https://crates.io/crates/sibgha/"
|
||||
repository = "https://gitlab.com/bjoernager/sibgha/"
|
||||
documentation = "https://docs.rs/polywave/"
|
||||
homepage = "https://crates.io/crates/polywave/"
|
||||
repository = "https://gitlab.com/bjoernager/polywave/"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[dependencies]
|
||||
bytemuck = { version = "1.22", optional = true, features = ["derive"] }
|
||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
zerocopy = { version = "0.8", optional = true, features = ["derive"] }
|
||||
wgpu-types = { version = "24.0", optional = true }
|
||||
bytemuck = { version = "1.22", optional = true, default-features = false, features = ["derive"] }
|
||||
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
|
||||
zerocopy = { version = "0.8", optional = true, default-features = false, features = ["derive", "simd"] }
|
||||
wgpu-types = { version = "24.0", optional = true, default-features = false }
|
||||
|
||||
[features]
|
||||
bytemuck = ["dep:bytemuck"]
|
||||
f128 = []
|
||||
f16 = []
|
||||
serde = ["dep:serde"]
|
||||
zerocopy = ["dep:zerocopy"]
|
||||
wgpu = ["dep:wgpu-types"]
|
||||
|
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Polywave
|
||||
|
||||
Vector-based colour manipulators.
|
150
src/component/mod.rs
Normal file
150
src/component/mod.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of
|
||||
// the Mozilla Public License, v. 2.0. If a copy of
|
||||
// the MPL was not distributed with this file, you
|
||||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
mod seal {
|
||||
/// Denotes a type suitable for use as a colour component.
|
||||
pub trait Component: Copy + Sized { }
|
||||
}
|
||||
|
||||
pub(crate) use seal::Component as SealedComponent;
|
||||
|
||||
/// Denotes a type suitable for use as a colour component.
|
||||
///
|
||||
/// Importantly, all components must be
|
||||
///
|
||||
/// Note that not all components are necessarily transformable; most colour spaces and formats require some form of floating- or fixed-point arithmetic for transformations to be at least be somewhat accurate.
|
||||
/// Only the most basic of colours spaces can thus be translated using simple integers.
|
||||
pub trait Component: SealedComponent + Copy + Sized {
|
||||
/// Lossily converts the component to [`f16`].
|
||||
///
|
||||
/// If `Self` additionally implements <code>[Into]<f16></code>, then this method must also be lossless.
|
||||
#[cfg(feature = "f16")]
|
||||
#[must_use]
|
||||
fn to_f16_lossy(self) -> f16;
|
||||
|
||||
/// Lossily converts the component to [`f32`].
|
||||
///
|
||||
/// If `Self` additionally implements <code>[Into]<f32></code>, then this method must also be lossless.
|
||||
#[must_use]
|
||||
fn to_f32_lossy(self) -> f32;
|
||||
|
||||
/// Lossily converts the component to [`f64`].
|
||||
///
|
||||
/// If `Self` additionally implements <code>[Into]<f64></code>, then this method must also be lossless.
|
||||
#[must_use]
|
||||
fn to_f64_lossy(self) -> f64;
|
||||
|
||||
/// Lossily converts the component to [`f128`].
|
||||
///
|
||||
/// If `Self` additionally implements <code>[Into]<f128></code>, then this method must also be lossless.
|
||||
#[cfg(feature = "f128")]
|
||||
#[must_use]
|
||||
fn to_f128_lossy(self) -> f128;
|
||||
}
|
||||
|
||||
macro_rules! impl_integer_component {
|
||||
{
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$tys:ty
|
||||
),+$(,)?
|
||||
} => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl ::polywave::SealedComponent for $tys { }
|
||||
|
||||
$(#[$attrs])*
|
||||
impl ::polywave::Component for $tys {
|
||||
#[cfg(feature = "f16")]
|
||||
#[inline(always)]
|
||||
fn to_f16_lossy(self) -> f16 {
|
||||
self as f16 / Self::MAX as f16
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_f32_lossy(self) -> f32 {
|
||||
self as f32 / Self::MAX as f32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_f64_lossy(self) -> f64 {
|
||||
self as f64 / Self::MAX as f64
|
||||
}
|
||||
|
||||
#[cfg(feature = "f128")]
|
||||
#[inline(always)]
|
||||
fn to_f128_lossy(self) -> f128 {
|
||||
self as f128 / Self::MAX as f128
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_float_component {
|
||||
{
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$tys:ty
|
||||
),+$(,)?
|
||||
} => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl ::polywave::SealedComponent for $tys { }
|
||||
|
||||
$(#[$attrs])*
|
||||
impl ::polywave::Component for $tys {
|
||||
#[cfg(feature = "f16")]
|
||||
#[inline(always)]
|
||||
fn to_f16_lossy(self) -> f16 {
|
||||
self as f16
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_f32_lossy(self) -> f32 {
|
||||
self as f32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_f64_lossy(self) -> f64 {
|
||||
self as f64
|
||||
}
|
||||
|
||||
#[cfg(feature = "f128")]
|
||||
#[inline(always)]
|
||||
fn to_f128_lossy(self) -> f128 {
|
||||
self as f128
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_integer_component! {
|
||||
u8,
|
||||
i8,
|
||||
u16,
|
||||
i16,
|
||||
u32,
|
||||
i32,
|
||||
u64,
|
||||
i64,
|
||||
u128,
|
||||
i128,
|
||||
}
|
||||
|
||||
impl_float_component! {
|
||||
f32,
|
||||
f64,
|
||||
|
||||
#[cfg(feature = "f16")]
|
||||
f16,
|
||||
|
||||
#[cfg(feature = "f128")]
|
||||
f128,
|
||||
}
|
13
src/error/mod.rs
Normal file
13
src/error/mod.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of
|
||||
// the Mozilla Public License, v. 2.0. If a copy of
|
||||
// the MPL was not distributed with this file, you
|
||||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
//! Error types.
|
||||
|
||||
mod rgba_u8_from_str_error;
|
||||
|
||||
pub use rgba_u8_from_str_error::RgbaU8FromStrError;
|
37
src/error/rgba_u8_from_str_error/mod.rs
Normal file
37
src/error/rgba_u8_from_str_error/mod.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
||||
/// A RGBA colour code could not be parsed.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum RgbaU8FromStrError {
|
||||
/// The RGBA colour code had an invalid length.
|
||||
InvalidLength(usize),
|
||||
|
||||
/// The RGBA colour code had no prefixed hash `#`.
|
||||
MissingHash,
|
||||
|
||||
/// The RGBA colour code had an otherwise unknown format.
|
||||
///
|
||||
/// This error is only emitted if neither of the two others is appropriate.
|
||||
UnknownFormat,
|
||||
}
|
||||
|
||||
impl Error for RgbaU8FromStrError { }
|
||||
|
||||
impl Display for RgbaU8FromStrError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Self::InvalidLength(len)
|
||||
=> write!(f, "rgba code has length `{len}` but should have been neither `4` or `7` or `9` octets long"),
|
||||
|
||||
Self::MissingHash
|
||||
=> write!(f, "rgba code is missing prefixed hash `#`"),
|
||||
|
||||
Self::UnknownFormat
|
||||
=> write!(f, "rgba code is of an otherwise unknown format"),
|
||||
}
|
||||
}
|
||||
}
|
22
src/lib.rs
22
src/lib.rs
|
@ -6,8 +6,26 @@
|
|||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
//! Vector-based colour manipulators.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#![no_std]
|
||||
|
||||
mod srgba8;
|
||||
#![cfg_attr(feature = "f16", feature(f16))]
|
||||
#![cfg_attr(feature = "f128", feature(f128))]
|
||||
|
||||
pub use srgba8::Srgba8;
|
||||
extern crate self as polywave;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate alloc;
|
||||
|
||||
pub mod error;
|
||||
|
||||
mod component;
|
||||
mod rgba;
|
||||
|
||||
pub use component::Component;
|
||||
pub use rgba::Rgba;
|
||||
|
||||
use component::SealedComponent;
|
||||
|
|
150
src/rgba/mod.rs
Normal file
150
src/rgba/mod.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of
|
||||
// the Mozilla Public License, v. 2.0. If a copy of
|
||||
// the MPL was not distributed with this file, you
|
||||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
mod test;
|
||||
|
||||
use crate::Component;
|
||||
use crate::error::RgbaU8FromStrError;
|
||||
|
||||
use core::fmt::{self, Debug, Display, Formatter};
|
||||
use core::ops::RangeInclusive;
|
||||
use core::str::FromStr;
|
||||
|
||||
/// An RGBA colour.
|
||||
///
|
||||
/// This type guarantees that its four channels -- red, green, blue, and alpha -- are stored sequentially in memory (in this order).
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "zerocopy", derive(zerocopy::FromZeros, zerocopy::Immutable, zerocopy::IntoBytes))]
|
||||
pub struct Rgba<T: Component>([T; 0x4]);
|
||||
|
||||
impl<T: Component> Rgba<T> {
|
||||
/// Constructs a new RGBA colour.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn new(r: T, g: T, b: T, a: T) -> Self {
|
||||
let data = [r, g, b, a];
|
||||
Self(data)
|
||||
}
|
||||
|
||||
/// Deconstructs an RGBA colour.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn get(self) -> (T, T, T, T) {
|
||||
let [r, g, b, a] = self.0;
|
||||
(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl Rgba<u8> {
|
||||
/// Constructs a new RGBA colour from [`u32`].
|
||||
///
|
||||
/// The `u32` value is reinterpreted as a four contiguous `u8` objects corresponding to each of the four channels.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn from_u32(value: u32) -> Self {
|
||||
let data = value.to_be_bytes();
|
||||
Self(data)
|
||||
}
|
||||
|
||||
/// Converts an RGBA colour to [`u32`].
|
||||
///
|
||||
/// This function is the inverse of [`from_u32`](Self::from_u32) (see there for more information).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn to_u32(self) -> u32 {
|
||||
let data = self.0;
|
||||
u32::from_be_bytes(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Rgba<u8> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let value = self.to_u32();
|
||||
|
||||
write!(f, "#{value:08X}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Component> From<(T, T, T, T)> for Rgba<T> {
|
||||
#[inline(always)]
|
||||
fn from((r, g, b, a): (T, T, T, T)) -> Self {
|
||||
Self::new(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Rgba<u8> {
|
||||
type Err = RgbaU8FromStrError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if !s.starts_with('#') {
|
||||
return Err(RgbaU8FromStrError::MissingHash);
|
||||
}
|
||||
|
||||
let get_int_in_range = |range: RangeInclusive<usize>| -> Result<u8, Self::Err> {
|
||||
let value = s.get(range).map(|s| u8::from_str_radix(s, 0x10));
|
||||
|
||||
if let Some(Ok(value)) = value {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(RgbaU8FromStrError::UnknownFormat)
|
||||
}
|
||||
};
|
||||
|
||||
let colour = match s.len() {
|
||||
0x4 => {
|
||||
let r = get_int_in_range(0x1..=0x1)? * 0x11;
|
||||
let g = get_int_in_range(0x2..=0x2)? * 0x11;
|
||||
let b = get_int_in_range(0x3..=0x3)? * 0x11;
|
||||
|
||||
Self::new(r, g, b, 0xFF)
|
||||
}
|
||||
|
||||
0x7 => {
|
||||
let r = get_int_in_range(0x1..=0x2)?;
|
||||
let g = get_int_in_range(0x3..=0x4)?;
|
||||
let b = get_int_in_range(0x5..=0x6)?;
|
||||
|
||||
Self::new(r, g, b, 0xFF)
|
||||
}
|
||||
|
||||
0x9 => {
|
||||
let r = get_int_in_range(0x1..=0x2)?;
|
||||
let g = get_int_in_range(0x3..=0x4)?;
|
||||
let b = get_int_in_range(0x5..=0x6)?;
|
||||
let a = get_int_in_range(0x7..=0x8)?;
|
||||
|
||||
Self::new(r, g, b, a)
|
||||
}
|
||||
|
||||
len => return Err(RgbaU8FromStrError::InvalidLength(len)),
|
||||
};
|
||||
|
||||
Ok(colour)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: We require `Into<f64>` as that also guran-
|
||||
// tees the losslessness of `to_f64_lossy`.
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl<T: Component + Into<f64>> From<Rgba<T>> for wgpu_types::Color {
|
||||
#[inline]
|
||||
fn from(value: Rgba<T>) -> Self {
|
||||
let (r, g, b, a) = value.get();
|
||||
|
||||
let r = r.to_f64_lossy();
|
||||
let g = g.to_f64_lossy();
|
||||
let b = b.to_f64_lossy();
|
||||
let a = a.to_f64_lossy();
|
||||
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
33
src/rgba/test.rs
Normal file
33
src/rgba/test.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of
|
||||
// the Mozilla Public License, v. 2.0. If a copy of
|
||||
// the MPL was not distributed with this file, you
|
||||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use crate::Rgba;
|
||||
|
||||
use alloc::format;
|
||||
use core::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_rgba_u8_display() {
|
||||
assert_eq!(format!("{}", Rgba::<u8>::from_u32(0xF0F8FFFF)), "#F0F8FFFF");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_u8_from_str() {
|
||||
assert_eq!(Rgba::<u8>::from_str("#639"), Ok(Rgba::new(0x66, 0x33, 0x99, 0xFF)));
|
||||
|
||||
assert_eq!(Rgba::<u8>::from_str("#00FF7F"), Ok(Rgba::new(0x00, 0xFF, 0x7F, 0xFF)));
|
||||
|
||||
assert_eq!(Rgba::<u8>::from_str("#FfD7007f"), Ok(Rgba::new(0xFF, 0xD7, 0x00, 0x7F)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_u8_from_u32() {
|
||||
assert_eq!(Rgba::<u8>::from_u32(0x80808080), Rgba::<u8>::new(0x80, 0x80, 0x80, 0x80));
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright 2025 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of
|
||||
// the Mozilla Public License, v. 2.0. If a copy of
|
||||
// the MPL was not distributed with this file, you
|
||||
// can obtain one at:
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
|
||||
use core::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
type Buffer = [u8; 0x4];
|
||||
|
||||
#[repr(align(0x4), C)]
|
||||
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern, bytemuck::NoUninit))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "zerocopy", derive(zerocopy::FromBytes, zerocopy::Immutable, zerocopy::IntoBytes))]
|
||||
pub struct Srgba8(Buffer);
|
||||
|
||||
impl Srgba8 {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
let buf = [r, g, b, a];
|
||||
Self(buf)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn from_u32(value: u32) -> Self {
|
||||
let buf = value.to_be_bytes();
|
||||
Self(buf)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn get(self) -> (u8, u8, u8, u8) {
|
||||
let [r, g, b, a] = self.0;
|
||||
(r, g, b, a)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn into_u32(self) -> u32 {
|
||||
let data = self.0;
|
||||
u32::from_be_bytes(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Srgba8 {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.get(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Srgba8 {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "#{:08X}", self.into_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(u8, u8, u8, u8)> for Srgba8 {
|
||||
#[inline(always)]
|
||||
fn from((r, g, b, a): (u8, u8, u8, u8)) -> Self {
|
||||
Self::new(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Srgba8 {
|
||||
#[inline(always)]
|
||||
fn from(value: u32) -> Self {
|
||||
Self::from_u32(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl From<Srgba8> for wgpu_types::Color {
|
||||
#[inline]
|
||||
fn from(value: Srgba8) -> Self {
|
||||
let (r, g, b, a) = value.get();
|
||||
|
||||
Self {
|
||||
r: f64::from(r) / f64::from(u8::MAX),
|
||||
g: f64::from(g) / f64::from(u8::MAX),
|
||||
b: f64::from(b) / f64::from(u8::MAX),
|
||||
a: f64::from(a) / f64::from(u8::MAX),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue