Colour for MoonBit: CSS syntax, colour spaces, gamut mapping, terminal colours and colour arithmetic.
let brand = @moonrgba.Color::decode("#0891b2")
brand.to_oklch().encode() // "oklch(0.60891 0.11094 221.72312)"
brand.mix(@moonrgba.Color::white(), space=@moonrgba.Space::Oklch).encode()
// "oklch(0.80446 0.05547 221.72312)"
brand.contrast(@moonrgba.Color::white()) // 3.6820433648230324
brand.to_ansi256().code() // 31@moonrgba.Color::decode("#123").encode() // "#123"
@moonrgba.Color::decode("rgb(10 20 30 / 50%)").encode() // "rgb(10 20 30 / 0.5)"
@moonrgba.Color::decode("lab(50% 50% -20%)").encode() // "lab(50 62.5 -25)"
@moonrgba.Color::decode("color(display-p3 .5 .2 .1)").encode()
// "color(display-p3 0.5 0.2 0.1)"
@moonrgba.Color::decode("currentcolor").encode() // "currentcolor"let refused : @moonrgba.Refused = try {
ignore(@moonrgba.Color::decode("rgb(1 2)"))
abort("unreachable")
} catch {
error => error
}
println("\{refused}") // at 7: got ), want a number| Syntax | Read | Write | Written by encode() |
|---|---|---|---|
| #rgb, #rgba, #rrggbb, #rrggbbaa | yes | yes | sRGB that is a whole byte per channel |
| rgb() rgba(), comma arguments | yes | — | the form belongs to an earlier grammar |
| rgb() rgba(), space arguments | yes | yes | sRGB that is not a whole byte per channel |
| hsl() hsla() | yes | yes | a colour written in HSL |
| hwb() | yes | yes | a colour written in HWB |
| lab(), lch() | yes | yes | a colour written in Lab or LCh |
| oklab(), oklch() | yes | yes | a colour written in Oklab or OkLCh |
| color(...) | yes | yes | a colour in one of the eight spaces it names |
| the 148 named colours | yes | with Format::Named | |
| transparent | yes | as #0000 | |
| currentcolor | yes | yes |
let hsl = @moonrgba.Color::hsl(210.0, 0.5, 0.4)
hsl.to_oklch().encode() // "oklch(0.49931 0.09866 250.43306)"
hsl.to_srgb().components() // (0.2, 0.4, 0.6)| Space | Components | Reached through |
|---|---|---|
| Srgb | red, green, blue 0–1 | the hub for the HSL family |
| SrgbLinear | red, green, blue 0–1 | D65 XYZ |
| Hsl, Hsv, Hwb | hue in degrees, then two fractions | sRGB |
| DisplayP3, DisplayP3Linear, Rec2020, A98Rgb | red, green, blue 0–1 | D65 XYZ, own matrix and curve |
| ProPhoto | red, green, blue 0–1 | D50 XYZ, then Bradford to D65 |
| Lab, Lch | lightness 0–100, then a and b or chroma and hue | D50 XYZ |
| Oklab, Oklch | lightness 0–1, then a and b or chroma and hue | D65 XYZ through LMS |
| XyzD50, XyzD65 | X, Y, Z, Y = 1 for white | Bradford between the two |
| YCbCr | luma 0–1, chroma −0.5–0.5 | sRGB, with BT.601, BT.709 or BT.2020 coefficients |
| Current | — | the unresolved currentcolor keyword |
let wide = @moonrgba.Color::oklch(0.7, 0.4, 30.0)
wide.in_gamut(space=@moonrgba.Space::Srgb) // false
wide.to_srgb().encode() // "color(srgb 1.31965 -0.44982 -0.31009)"
wide.clip(space=@moonrgba.Space::Srgb).encode() // "#f00"
wide.to_gamut(space=@moonrgba.Space::Srgb).encode() // "rgb(255 88.00945 67.46665)"
wide.to_gamut(space=@moonrgba.Space::Srgb).to_oklch().encode()
// "oklch(0.6831 0.2062 30.18163)"let red = @moonrgba.Color::rgb(255, 0, 0)
let blue = @moonrgba.Color::rgb(0, 0, 255)
red.mix(blue, space=@moonrgba.Space::Srgb).encode() // "rgb(127.5 0 127.5)"
red.mix(blue, space=@moonrgba.Space::Oklab, weight=0.3).encode()
// "oklab(0.5048 0.04474 -0.18032)"
@moonrgba.Color::hsl(350.0, 1.0, 0.5)
.mix(@moonrgba.Color::hsl(10.0, 1.0, 0.5), space=@moonrgba.Space::Hsl, hue=Longer)
.hue() // 180let ink = @moonrgba.Color::black()
let paper = @moonrgba.Color::white()
ink.contrast(paper) // 21
ink.apca(paper) // 106.04067321268862
paper.apca(ink) // -107.88473318309848| Measure | Space | Note |
|---|---|---|
| E76 | Lab | the straight-line distance |
| E94 | Lab | graphic-arts weights; the first colour is the reference |
| E2000 | Lab | the current CIE recommendation |
| Ok | Oklab | no weights needed; a just-noticeable difference is 0.02 |
let brand = @moonrgba.Color::decode("#0891b2")
brand.to_ansi16() // cyan
brand.to_ansi256().code() // 31
brand.rgb8() // (8, 145, 178)
@moonrgba.Ansi256::of(196).color().encode() // "#f00"pub(all) struct Color {
space : Space
x : Double
y : Double
z : Double
alpha : Double
}println("\{@moonrgba.Color::decode("#0891b2")}") // #0891b2| Call | What it does |
|---|---|
| Color::decode(text) | read a CSS colour; raises Refused |
| Color::decode_opt(text) | the same, None instead of raising |
| Color::encode(format?) | write CSS, in the shortest exact spelling |
| Color::of(space, x, y, z, alpha?) | a colour from components already in a space |
| Color::srgb, rgb, hsl, hwb, lab, lch, oklab, oklch, xyz_d65, xyz_d50, display_p3, rec2020, a98_rgb, prophoto, ycbcr | a colour in that space |
| Color::of_name, Color::name | the 148 names, both ways |
| Color::to_srgb, to_hsl, to_lab, to_oklch and the rest, to_space | the same colour in another space |
| Color::in_gamut, clip, to_gamut | decide what to do with a colour a display cannot show |
| Color::mix, lighten, darken, saturate, desaturate, fade | combining and nudging |
| Color::contrast, apca, luminance | how readable a pair is |
| Color::delta_e | how far apart two colours are |
| Color::to_ansi16, to_ansi256, rgb8 | into a terminal's palette |
| Color::to_cmyk, Cmyk::to_color | into print, and back |
| Color::components, hue, chroma, lightness, saturation, with_components, with_alpha, resolve | looking inside, and putting it back together |
| Space::code, Space::of, is_polar, is_predefined, has_gamut | what a space is |
| space | x | y | z |
|---|---|---|---|
| Srgb, SrgbLinear, DisplayP3, Rec2020, A98Rgb, ProPhoto | red | green | blue |
| Hsl | hue, degrees | saturation | lightness |
| Hsv | hue, degrees | saturation | value |
| Hwb | hue, degrees | whiteness | blackness |
| Lab | lightness, 0–100 | a | b |
| Lch | lightness, 0–100 | chroma | hue, degrees |
| Oklab | lightness, 0–1 | a | b |
| Oklch | lightness, 0–1 | chroma | hue, degrees |
| XyzD50, XyzD65 | X | Y | Z |
| YCbCr | luma | blue difference | red difference |
| Current | — | — | — |
Install
Download zipColour for MoonBit: CSS syntax, colour spaces, gamut mapping, terminal colours and colour arithmetic.