#color #macro #rgba #author #syntax #generalized #meta

macro colorthis

Meta macros that aid macro authors to create colors from a generalized syntax

2 releases

0.1.1 Oct 15, 2023
0.1.0 Oct 15, 2023

#2111 in Procedural macros


Used in bevy_aoui_widgets

MIT/Apache

41KB
777 lines

colorthis

Crates.io Docs

Meta macros that aid macro authors to create colors from a generalized syntax.

General Syntax

rgb!($path: path, $color_syntax: tt [=> {$($fields: ident)*}])

Where path is a function or a struct constructor

If fields are not specified,

rgba!(Cmyk, [123, 155, 224, 155]);

produces

Cmyk(123, 155, 224, 155);

If fields are specified,

rgba!(Cmyk, [123, 155, 224, 155] => {c, m, y, k});

produces

Cmyk {
    c: 123,
    m: 155,
    y: 224,
    k: 155,
};

Populating a larger struct is allowed as long as the struct implements Default.

# use colorthis::rgba;
#[derive(Default)]
struct PixelData {
    r: u8, g: u8, b: u8, a: u8,
    z: u8, brightness: u8, magic_number: u8
}
rgba!(PixelData, [1, 2, 3, 4] => {r, g, b, a, _});

produces

PixelData {
    r: 1,
    g: 2,
    b: 3,
    a: 4,
    ..Default::default()
};

Example usage

macro_rules! bevy_rgba {
    ($color: tt) => {
        ::colorthis::rgbaf!(::bevy::prelude::Color::Rgba, $color => {red, green, blue, alpha})
    };
    ($($colors: literal),* $(,)?) => {
        ::colorthis::rgbaf!(::bevy::prelude::Color::Rgba, [$($colors),*] => {red, green, blue, alpha})
    };
}
bevy_rgba!("00EEFFFF");
bevy_rgba!("#AAEE22");
bevy_rgba!(0xAABBCC);
bevy_rgba!(72, 184, 255, 255);
bevy_rgba!(0.23, 0.44, 0.89, 0.50);
bevy_rgba!(Red);
bevy_rgba!(Violet800);

Color Syntax

The color is always a TokenTree tt.

  • Bracketed numbers: [0.3, 0.72, 0.98], [124, 54, 87, 255]
  • Parenthesised expressions: (0.3, 0.72, 0.98), (r, g, b + g, a + 0.5)
  • Splat syntax: [0.3; 3], [0.3; 3, 0.8], [0.7; 4]
  • Hex strings: "AABBCC", "AABBCCFF", "#AABBCC", "#AABBCCFF"
  • Hex number literals: 0xAABBCC, 0xAABBCCFF
  • CSS color names: Red, Blue
  • TailwindCSS color names: Red100, Sky400

Details

Bracketed Numbers

If all values are integers, they are considered to be in range 0..=255.

assert_eq!(rgba!(Color, [32, 144, 220, 125]), Color(32,144,220,125));

If any value is a float, values are considered to be in range 0.0..=1.0.

Therefore this fails to compile since numbers like 144 overflows this bounds.

assert_eq!(rgba!(Color, [0.5, 144, 220, 125]), Color(32, 144, 220, 125));

However if all values are 0s or 1s, and the macro invoked is rgbf!() or rgbaf!() 1s are treated as 1.0s.

assert_eq!(rgbaf!(ColorF, [255, 255, 255, 255]), ColorF(1.0, 1.0, 1.0, 1.0));
assert_eq!(rgbaf!(ColorF, [1.0, 0.5, 1, 0]), ColorF(1.0, 0.5, 1.0, 0.0));
assert_eq!(rgbaf!(ColorF, [1, 0, 1, 0]), ColorF(1.0, 0.0, 1.0, 0.0));

Parenthesised Expressions

Currently we do not modify the expression or provide type conversion, aside from validating the number of expressions, and providing default alpha value if needed.

Splat Syntax

  • [v; 3] means [v, v, v, 255]
  • [v; 3, a] means [v, v, v, a]
  • [v; 4] means [v, v, v, v]

Color Names

We relies on a crate to parse and generate these data at compile time. No external support required.

Feature Flags

unchecked and clamp

By default, we assert integers are in 0..=255, floats are in 0.0..=1.0

if unchecked is not specified, this fails

rgba!(color, [1000, 255, 128, 0]); // 1000 is not in 0..=255

With unchecked, this might compile, assuming color accepts 1000 as an input.

rgba!(color, [1000, 255, 128, 0]);

With clamp, this compiles and clamps 1000 into 255

rgba!(color, [1000, 255, 128, 0]); // produces color(255, 255, 128, 0)

compact

Compact allows 3 or 4 letter compact colors to be compiled.

rgba!(color, 0xABC); // compiles to 0xAABBCC
rgba!(color, "1234"); // compiles to "11223344"
rgba!(color, "#FFF"); // compiles to "FFFFFF"

Dependencies

~235–310KB