/*
5 * RafaĆ Siejakowski <
rs@
rs-math.net>
6 * Martin Owens <doctormo@geek-2.com>
8 * Copyright (C) 2023 Authors
9 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
53 double c = std::hypot(in_out[1], in_out[2]);
55 Geom::Angle const hue_angle = std::atan2(in_out[2], in_out[1]);
67struct ChromaLineCoefficients
79 double lcos2, lcossin, lsin2;
83 double cos3, cos2sin, cossin2, sin3;
92 .l2cos = 5.83279532899080641005754476131631984,
93 .l2sin = 2.3780791275435732378965655753413412
96 .lcos2 = 1.81614129917652075864819542521099165275,
97 .lcossin = 2.11851258971260413543962953223104329409,
98 .lsin2 = 1.68484527361538384522450980300698198391
101 .cos3 = 0.257535869797624151773507242289856932594,
102 .cos2sin = 0.414490345667882332785000888243122224651,
103 .cossin2 = 0.126596511492002610582126014059213892767,
104 .sin3 = -0.455702039844046560333204117380816048203
110 .l2cos = -2.243030176177044107983968331289088261,
111 .l2sin = 0.00129441240977850026657772225608
114 .lcos2 = -0.5187087369791308621879921351291952375,
115 .lcossin = -0.7820717390897833607054953914674219281,
116 .lsin2 = -1.8531911425339782749638630868227383795
119 .cos3 = -0.0817959138495637068389017598370049459,
120 .cos2sin = -0.1239788660641220973883495153116480854,
121 .cossin2 = 0.0792215342150077349794741576353537047,
122 .sin3 = 0.7218132301017783162780535454552058572
128 .l2cos = -0.2406412780923628220925350522352767957,
129 .l2sin = -6.48404701978782955733370693958213669
132 .lcos2 = 0.015528352128452044798222201797574285162,
133 .lcossin = 1.153466975472590255156068122829360981648,
134 .lsin2 = 8.535379923500727607267514499627438513637
137 .cos3 = -0.0006573855374563134769075967180540368,
138 .cos2sin = -0.0519029179849443823389557527273309386,
139 .cossin2 = -0.763927972885238036962716856256210617,
140 .sin3 = -3.67825541507929556013845659620477582
147struct ConstraintMonomials
149 double l, l2, l3,
c, c2, c3, s, s2, s3;
150 ConstraintMonomials(
double l,
double h)
176 std::array<double, 4>
result;
179 result[1] = coeffs.c1.l2cos * m.l2 * m.c + coeffs.c1.l2sin * m.l2 * m.s;
180 result[2] = coeffs.c2.lcos2 * m.l * m.c2 + coeffs.c2.lcossin * m.l * m.c * m.s + coeffs.c2.lsin2 * m.l * m.s2;
182 coeffs.c3.cos3 * m.c3 + coeffs.c3.cos2sin * m.c2 * m.s + coeffs.c3.cossin2 * m.c * m.s2 + coeffs.c3.sin3 * m.s3;
209 static double const EPS = 1e-7;
210 if (l < EPS || l > 1.0 - EPS) {
215 auto const process_root = [&](
double root) ->
bool {
219 if (chroma_bound >
root) {
226 auto const monomials = ConstraintMonomials(l, h);
227 for (
unsigned i = 0; i < 3; i++) {
233 if (process_root(
root)) {
240 if (process_root(
root)) {
273 double next_chroma_bound;
274 double const step = 360.0 / 1024.0;
278 double const initial_chroma = chroma_bound * s;
280 double const final_chroma = next_chroma_bound * s;
282 for (
unsigned j = 0; j < interval_length; j++) {
283 double const c =
Geom::lerp(
static_cast<double>(j) / interval_length, initial_chroma, final_chroma);
291 chroma_bound = next_chroma_bound;
301 if (chromax == 0.0) {
302 uint8_t
const bw = (l > 0.9) ? 0xFF : 0x00;
303 for (
size_t i = 0; i < 1024; i++) {
310 double const chroma_step = chromax / 1024.0;
312 for (
size_t i = 0; i < 1024; i++) {
333 double next_chroma_bound;
334 double const step = 1.0 / 1024.0;
338 double const initial_chroma = chroma_bound * s;
340 double const final_chroma = next_chroma_bound * s;
342 for (
unsigned j = 0; j < interval_length; j++) {
343 double const c =
Geom::lerp(
static_cast<double>(j) / interval_length, initial_chroma, final_chroma);
351 chroma_bound = next_chroma_bound;
383 if (opacity && values.size() == 4)
Various trigoniometric helper functions.
Wrapper for angular values.
static Angle from_degrees(Coord d)
Create an angle from its measure in degrees.
Coord radians0() const
Get the angle as positive radians.
static bool append_css_value(std::istringstream &ss, std::vector< double > &output, bool &end, char const sep=0x0, double scale=1.0)
Parse a CSS color number and format it according to it's unit.
bool parse(std::istringstream &input, std::vector< double > &output) const override
static void toOkLab(std::vector< double > &output)
Convert a color from the the OkLch colorspace to the OKLab colorspace.
static double max_chroma(double l, double h)
std::string toString(std::vector< double > const &values, bool opacity) const override
Print the Lab color to a CSS string.
static void fromOkLab(std::vector< double > &output)
Convert a color from the the OKLab colorspace to the OkLch colorspace.
constexpr uint32_t SP_COLOR_F_TO_U(double v)
vector< vpsc::Rectangle * > rs
std::unordered_map< std::string, std::unique_ptr< SPDocument > > map
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
constexpr Coord infinity()
Get a value representing infinity.
void sincos(double angle, double &sin_, double &cos_)
Simultaneously compute a sine and a cosine of the same angle.
std::vector< Coord > solve_cubic(Coord a, Coord b, Coord c, Coord d)
Analytically solve cubic equation.
uint8_t const * render_hue_scale(double s, double l, std::array< uint8_t, 4 *1024 > *map)
uint8_t const * render_saturation_scale(double h, double l, std::array< uint8_t, 4 *1024 > *map)
unsigned const COLOR_SCALE_INTERVALS
How many intervals a color scale should be subdivided into for the chroma bounds probing.
constexpr double CHROMA_SCALE
constexpr double HUE_SCALE
uint8_t const * render_lightness_scale(double h, double s, std::array< uint8_t, 4 *1024 > *map)
ChromaLineCoefficients const LAB_BOUNDS[]
static std::array< double, 4 > component_coefficients(unsigned index, ConstraintMonomials const &m)
Find the coefficients of the cubic polynomial expressing the linear R, G or B component as a function...
Polynomial in canonical (monomial) basis.