While the implementation has been carefully modularized from day 1, the public
API of prettypretty was small enough to fit into a single module. However, since
I was adding new features that required the introduction of new public types, I
decided to modularize the public API as well. New modules include [error
],
[gamut
], [spectrum
], [style
], and [trans
].
Other noteworthy new features are:
- Add [
Illuminant
] and [Observer
] to represent critical spectral distributions. The CIE's 2º standard observer for 1931 and 2015 as well as the D65 illuminant are included at one-nanometer resolution. - Add [
ColorSpace::gamut
] for traversing RGB color space boundaries. The method returns a [GamutTraversal
] iterator yielding [GamutTraversalStep
]s. - Add [
Color::hue_chroma
] and [Color::xy_chromaticity
] for plotting colors in 2D.
- Rename
Sampler
toTranslator
. - Edit documentation for correctness and clarity.
- Like [
Color::from_24bit
], thergb
macro creates sRGB colors from 24-bit integer coordinates. Unlike the method, the macro can appear in const expressions.
- Rename
Sampler::adjust
to [Sampler::cap
] - Improve documentation with many small edits, new overview and summary,
and disabling the
pyffi
feature flag on docs.rs
- [
Fidelity::from_environment
] now correctly classifies iTerm 3.x as having full fidelity.
As it turns out, v0.9.0 is the new v0.1.0. At least, it feels that way writing up the changes. Thankfully, minor version numbers are not limited to single decimal digits…
This release combines the Rust and Python versions of prettypretty into one
coherent codebase. The core color functionality is now implemented in Rust only
and, with the help of PyO3 and
Maturin, exposed to Python as an extension module.
Having published several
research papers on foreign
function interfaces, I can
state with some authority that PyO3's integration between Rust and Python is
nothing but impressive. But its macro-based implementation is brittle and often
gets in the way of building a pure Rust library and an extension module from the
same codebase. The only viable workarounds were to duplicate some methods and to
spread methods over up to three impl
blocks. But hey, it works really well! 🎉
Sampler
is the new one-stop abstraction for translating colors, from terminal to
high-resolution, high-resolution to terminal, and terminal to terminal colors.
It makes translation between color representation more convenient and it is more
powerful.
Notably,
Sampler::to_ansi_hue_lightness
implements a new algorithm for converting high-resolution colors to the 16 ANSI
colors. For color themes that roughly observe the semantics of ANSI colors
(e.g., when sorted by hue, red and bright red come before yellow and bright
yellow, which in turn come before green and bright green and so on), it produces
more accurate results by first using hue to select a pair of regular and bright
ANSI colors and then lightness to select the best match. For color themes that
violate the new algorithm's invariants,
Sampler::to_ansi
transparently and automatically falls back to brute force search for the closest
color.
Prettypretty now supports more color spaces:
- Oklrab and Oklrch revise Oklab's lightness estimate to be as uniform as CIELAB's equivalent and proven component.
- Rec. 2020 is a popular but purely aspirational color space.
High-resolution colors are simpler to use and support more operations:
Color
now is immutable. While immutability may slightly increase prettypretty's memory overhead, a mutable color abstraction in Rust should probably use interior mutability and heap-allocated color coordinates. The potential for saving 16 or 24 bytes here or there does not seem to justify the attendant complexity. Immutability it is.Color::interpolate
implements CSS Color 4's interpolation algorithm, including the specification's rather elaborate rules for carrying forward missing components and for selecting the hue interpolation strategy.Color::lighten
andColor::darken
keep colors in line with your moods.
Terminal colors have a more coherent model:
TerminalColor
combines the different kinds of colors supported by terminals, i.e., the default foreground and background colors, ANSI colors, 8-bit colors including the 6x6x6 embedded RGB cube and the 24-step gray gradient, as well as 24-bit "true" colors.DefaultColor
correctly models that there are two, albeit context-sensitive default colors, one for the foreground and one for the background.