@atlaskit/tokens 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/artifacts/atlassian-dark-token-value-for-contrast-check.js +24 -0
  3. package/dist/cjs/artifacts/atlassian-light-token-value-for-contrast-check.js +24 -0
  4. package/dist/cjs/artifacts/themes/atlassian-dark-new-input-border.js +2 -2
  5. package/dist/cjs/artifacts/tokens-raw/atlassian-dark-new-input-border.js +3 -3
  6. package/dist/cjs/constants.js +3 -1
  7. package/dist/cjs/custom-theme.js +108 -0
  8. package/dist/cjs/get-token-value.js +1 -1
  9. package/dist/cjs/get-token.js +1 -1
  10. package/dist/cjs/set-global-theme.js +156 -59
  11. package/dist/cjs/tokens/atlassian-dark-new-input-border/color/border.js +1 -1
  12. package/dist/cjs/utils/color-utils.js +178 -0
  13. package/dist/cjs/utils/custom-theme-loading-utils.js +47 -0
  14. package/dist/cjs/utils/custom-theme-token-contrast-check.js +74 -0
  15. package/dist/cjs/utils/generate-custom-color-ramp.js +213 -0
  16. package/dist/cjs/utils/hash.js +17 -0
  17. package/dist/cjs/utils/hct-color-utils/color-utils.js +310 -0
  18. package/dist/cjs/utils/hct-color-utils/contrast.js +188 -0
  19. package/dist/cjs/utils/hct-color-utils/hct.js +1036 -0
  20. package/dist/cjs/utils/hct-color-utils/index.js +32 -0
  21. package/dist/cjs/utils/hct-color-utils/math-utils.js +159 -0
  22. package/dist/cjs/utils/theme-loading.js +1 -1
  23. package/dist/cjs/utils/theme-state-transformer.js +1 -1
  24. package/dist/cjs/version.json +1 -1
  25. package/dist/es2019/artifacts/atlassian-dark-token-value-for-contrast-check.js +17 -0
  26. package/dist/es2019/artifacts/atlassian-light-token-value-for-contrast-check.js +17 -0
  27. package/dist/es2019/artifacts/themes/atlassian-dark-new-input-border.js +2 -2
  28. package/dist/es2019/artifacts/tokens-raw/atlassian-dark-new-input-border.js +3 -3
  29. package/dist/es2019/constants.js +1 -0
  30. package/dist/es2019/custom-theme.js +77 -0
  31. package/dist/es2019/get-token-value.js +1 -1
  32. package/dist/es2019/get-token.js +1 -1
  33. package/dist/es2019/set-global-theme.js +67 -13
  34. package/dist/es2019/tokens/atlassian-dark-new-input-border/color/border.js +1 -1
  35. package/dist/es2019/utils/color-utils.js +154 -0
  36. package/dist/es2019/utils/custom-theme-loading-utils.js +31 -0
  37. package/dist/es2019/utils/custom-theme-token-contrast-check.js +68 -0
  38. package/dist/es2019/utils/generate-custom-color-ramp.js +187 -0
  39. package/dist/es2019/utils/hash.js +10 -0
  40. package/dist/es2019/utils/hct-color-utils/color-utils.js +286 -0
  41. package/dist/es2019/utils/hct-color-utils/contrast.js +161 -0
  42. package/dist/es2019/utils/hct-color-utils/hct.js +931 -0
  43. package/dist/es2019/utils/hct-color-utils/index.js +3 -0
  44. package/dist/es2019/utils/hct-color-utils/math-utils.js +145 -0
  45. package/dist/es2019/utils/theme-loading.js +2 -2
  46. package/dist/es2019/utils/theme-state-transformer.js +3 -1
  47. package/dist/es2019/version.json +1 -1
  48. package/dist/esm/artifacts/atlassian-dark-token-value-for-contrast-check.js +17 -0
  49. package/dist/esm/artifacts/atlassian-light-token-value-for-contrast-check.js +17 -0
  50. package/dist/esm/artifacts/themes/atlassian-dark-new-input-border.js +2 -2
  51. package/dist/esm/artifacts/tokens-raw/atlassian-dark-new-input-border.js +3 -3
  52. package/dist/esm/constants.js +1 -0
  53. package/dist/esm/custom-theme.js +98 -0
  54. package/dist/esm/get-token-value.js +1 -1
  55. package/dist/esm/get-token.js +1 -1
  56. package/dist/esm/set-global-theme.js +149 -60
  57. package/dist/esm/tokens/atlassian-dark-new-input-border/color/border.js +1 -1
  58. package/dist/esm/utils/color-utils.js +162 -0
  59. package/dist/esm/utils/custom-theme-loading-utils.js +38 -0
  60. package/dist/esm/utils/custom-theme-token-contrast-check.js +65 -0
  61. package/dist/esm/utils/generate-custom-color-ramp.js +202 -0
  62. package/dist/esm/utils/hash.js +10 -0
  63. package/dist/esm/utils/hct-color-utils/color-utils.js +285 -0
  64. package/dist/esm/utils/hct-color-utils/contrast.js +181 -0
  65. package/dist/esm/utils/hct-color-utils/hct.js +1029 -0
  66. package/dist/esm/utils/hct-color-utils/index.js +3 -0
  67. package/dist/esm/utils/hct-color-utils/math-utils.js +145 -0
  68. package/dist/esm/utils/theme-loading.js +2 -2
  69. package/dist/esm/utils/theme-state-transformer.js +1 -1
  70. package/dist/esm/version.json +1 -1
  71. package/dist/types/artifacts/atlassian-dark-token-value-for-contrast-check.d.ts +17 -0
  72. package/dist/types/artifacts/atlassian-light-token-value-for-contrast-check.d.ts +17 -0
  73. package/dist/types/artifacts/themes/atlassian-dark-new-input-border.d.ts +2 -2
  74. package/dist/types/artifacts/tokens-raw/atlassian-dark-new-input-border.d.ts +1 -1
  75. package/dist/types/constants.d.ts +1 -0
  76. package/dist/types/custom-theme.d.ts +30 -0
  77. package/dist/types/index.d.ts +1 -0
  78. package/dist/types/set-global-theme.d.ts +9 -3
  79. package/dist/types/tokens/atlassian-dark/utility/utility.d.ts +1 -1
  80. package/dist/types/tokens/atlassian-light/utility/utility.d.ts +1 -1
  81. package/dist/types/tokens/default/utility/utility.d.ts +1 -1
  82. package/dist/types/utils/color-utils.d.ts +10 -0
  83. package/dist/types/utils/custom-theme-loading-utils.d.ts +11 -0
  84. package/dist/types/utils/custom-theme-token-contrast-check.d.ts +20 -0
  85. package/dist/types/utils/generate-custom-color-ramp.d.ts +19 -0
  86. package/dist/types/utils/hash.d.ts +1 -0
  87. package/dist/types/utils/hct-color-utils/color-utils.d.ts +131 -0
  88. package/dist/types/utils/hct-color-utils/contrast.d.ts +78 -0
  89. package/dist/types/utils/hct-color-utils/hct.d.ts +137 -0
  90. package/dist/types/utils/hct-color-utils/index.d.ts +3 -0
  91. package/dist/types/utils/hct-color-utils/math-utils.d.ts +86 -0
  92. package/dist/types-ts4.5/artifacts/atlassian-dark-token-value-for-contrast-check.d.ts +17 -0
  93. package/dist/types-ts4.5/artifacts/atlassian-light-token-value-for-contrast-check.d.ts +17 -0
  94. package/dist/types-ts4.5/artifacts/themes/atlassian-dark-new-input-border.d.ts +2 -2
  95. package/dist/types-ts4.5/artifacts/tokens-raw/atlassian-dark-new-input-border.d.ts +1 -1
  96. package/dist/types-ts4.5/constants.d.ts +1 -0
  97. package/dist/types-ts4.5/custom-theme.d.ts +30 -0
  98. package/dist/types-ts4.5/index.d.ts +1 -0
  99. package/dist/types-ts4.5/set-global-theme.d.ts +9 -3
  100. package/dist/types-ts4.5/tokens/atlassian-dark/utility/utility.d.ts +1 -1
  101. package/dist/types-ts4.5/tokens/atlassian-light/utility/utility.d.ts +1 -1
  102. package/dist/types-ts4.5/tokens/default/utility/utility.d.ts +1 -1
  103. package/dist/types-ts4.5/utils/color-utils.d.ts +27 -0
  104. package/dist/types-ts4.5/utils/custom-theme-loading-utils.d.ts +11 -0
  105. package/dist/types-ts4.5/utils/custom-theme-token-contrast-check.d.ts +20 -0
  106. package/dist/types-ts4.5/utils/generate-custom-color-ramp.d.ts +19 -0
  107. package/dist/types-ts4.5/utils/hash.d.ts +1 -0
  108. package/dist/types-ts4.5/utils/hct-color-utils/color-utils.d.ts +131 -0
  109. package/dist/types-ts4.5/utils/hct-color-utils/contrast.d.ts +78 -0
  110. package/dist/types-ts4.5/utils/hct-color-utils/hct.d.ts +137 -0
  111. package/dist/types-ts4.5/utils/hct-color-utils/index.d.ts +3 -0
  112. package/dist/types-ts4.5/utils/hct-color-utils/math-utils.d.ts +86 -0
  113. package/figma/atlassian-dark-new-input-border.json +1 -1
  114. package/package.json +35 -40
  115. package/report.api.md +24 -1
  116. package/tmp/api-report-tmp.d.ts +0 -1132
@@ -0,0 +1,931 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ /**
3
+ * Below lines are copied from @material/material-color-utilities.
4
+ * Do not modify it.
5
+ */
6
+
7
+ /**
8
+ * @license
9
+ * Copyright 2021 Google LLC
10
+ *
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ */
23
+
24
+ import * as utils from './color-utils';
25
+ import * as math from './math-utils';
26
+
27
+ /**
28
+ * A color system built using CAM16 hue and chroma, and L* from
29
+ * L*a*b*.
30
+ *
31
+ * Using L* creates a link between the color system, contrast, and thus
32
+ * accessibility. Contrast ratio depends on relative luminance, or Y in the XYZ
33
+ * color space. L*, or perceptual luminance can be calculated from Y.
34
+ *
35
+ * Unlike Y, L* is linear to human perception, allowing trivial creation of
36
+ * accurate color tones.
37
+ *
38
+ * Unlike contrast ratio, measuring contrast in L* is linear, and simple to
39
+ * calculate. A difference of 40 in HCT tone guarantees a contrast ratio >= 3.0,
40
+ * and a difference of 50 guarantees a contrast ratio >= 4.5.
41
+ */
42
+
43
+ /**
44
+ * HCT, hue, chroma, and tone. A color system that provides a perceptually
45
+ * accurate color measurement system that can also accurately render what colors
46
+ * will appear as in different lighting environments.
47
+ */
48
+ export class Hct {
49
+ /**
50
+ * @param hue 0 <= hue < 360; invalid values are corrected.
51
+ * @param chroma 0 <= chroma < ?; Informally, colorfulness. The color
52
+ * returned may be lower than the requested chroma. Chroma has a different
53
+ * maximum for any given hue and tone.
54
+ * @param tone 0 <= tone <= 100; invalid values are corrected.
55
+ * @return HCT representation of a color in default viewing conditions.
56
+ */
57
+
58
+ static from(hue, chroma, tone) {
59
+ return new Hct(HctSolver.solveToInt(hue, chroma, tone));
60
+ }
61
+
62
+ /**
63
+ * @param argb ARGB representation of a color.
64
+ * @return HCT representation of a color in default viewing conditions
65
+ */
66
+ static fromInt(argb) {
67
+ return new Hct(argb);
68
+ }
69
+ toInt() {
70
+ return this.argb;
71
+ }
72
+
73
+ /**
74
+ * A number, in degrees, representing ex. red, orange, yellow, etc.
75
+ * Ranges from 0 <= hue < 360.
76
+ */
77
+ get hue() {
78
+ return this.internalHue;
79
+ }
80
+
81
+ /**
82
+ * @param newHue 0 <= newHue < 360; invalid values are corrected.
83
+ * Chroma may decrease because chroma has a different maximum for any given
84
+ * hue and tone.
85
+ */
86
+ set hue(newHue) {
87
+ this.setInternalState(HctSolver.solveToInt(newHue, this.internalChroma, this.internalTone));
88
+ }
89
+ get chroma() {
90
+ return this.internalChroma;
91
+ }
92
+
93
+ /**
94
+ * @param newChroma 0 <= newChroma < ?
95
+ * Chroma may decrease because chroma has a different maximum for any given
96
+ * hue and tone.
97
+ */
98
+ set chroma(newChroma) {
99
+ this.setInternalState(HctSolver.solveToInt(this.internalHue, newChroma, this.internalTone));
100
+ }
101
+
102
+ /**
103
+ * Lightness. Ranges from 0 to 100.
104
+ */
105
+ get tone() {
106
+ return this.internalTone;
107
+ }
108
+
109
+ /**
110
+ * @param newTone 0 <= newTone <= 100; invalid valids are corrected.
111
+ * Chroma may decrease because chroma has a different maximum for any given
112
+ * hue and tone.
113
+ */
114
+ set tone(newTone) {
115
+ this.setInternalState(HctSolver.solveToInt(this.internalHue, this.internalChroma, newTone));
116
+ }
117
+ constructor(argb) {
118
+ this.argb = argb;
119
+ const cam = Cam16.fromInt(argb);
120
+ this.internalHue = cam.hue;
121
+ this.internalChroma = cam.chroma;
122
+ this.internalTone = utils.lstarFromArgb(argb);
123
+ this.argb = argb;
124
+ }
125
+ setInternalState(argb) {
126
+ const cam = Cam16.fromInt(argb);
127
+ this.internalHue = cam.hue;
128
+ this.internalChroma = cam.chroma;
129
+ this.internalTone = utils.lstarFromArgb(argb);
130
+ this.argb = argb;
131
+ }
132
+
133
+ /**
134
+ * Translates a color into different [ViewingConditions].
135
+ *
136
+ * Colors change appearance. They look different with lights on versus off,
137
+ * the same color, as in hex code, on white looks different when on black.
138
+ * This is called color relativity, most famously explicated by Josef Albers
139
+ * in Interaction of Color.
140
+ *
141
+ * In color science, color appearance models can account for this and
142
+ * calculate the appearance of a color in different settings. HCT is based on
143
+ * CAM16, a color appearance model, and uses it to make these calculations.
144
+ *
145
+ * See [ViewingConditions.make] for parameters affecting color appearance.
146
+ */
147
+ inViewingConditions(vc) {
148
+ // 1. Use CAM16 to find XYZ coordinates of color in specified VC.
149
+ const cam = Cam16.fromInt(this.toInt());
150
+ const viewedInVc = cam.xyzInViewingConditions(vc);
151
+
152
+ // 2. Create CAM16 of those XYZ coordinates in default VC.
153
+ const recastInVc = Cam16.fromXyzInViewingConditions(viewedInVc[0], viewedInVc[1], viewedInVc[2], ViewingConditions.make());
154
+
155
+ // 3. Create HCT from:
156
+ // - CAM16 using default VC with XYZ coordinates in specified VC.
157
+ // - L* converted from Y in XYZ coordinates in specified VC.
158
+ const recastHct = Hct.from(recastInVc.hue, recastInVc.chroma, utils.lstarFromY(viewedInVc[1]));
159
+ return recastHct;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * CAM16, a color appearance model. Colors are not just defined by their hex
165
+ * code, but rather, a hex code and viewing conditions.
166
+ *
167
+ * CAM16 instances also have coordinates in the CAM16-UCS space, called J*, a*,
168
+ * b*, or jstar, astar, bstar in code. CAM16-UCS is included in the CAM16
169
+ * specification, and should be used when measuring distances between colors.
170
+ *
171
+ * In traditional color spaces, a color can be identified solely by the
172
+ * observer's measurement of the color. Color appearance models such as CAM16
173
+ * also use information about the environment where the color was
174
+ * observed, known as the viewing conditions.
175
+ *
176
+ * For example, white under the traditional assumption of a midday sun white
177
+ * point is accurately measured as a slightly chromatic blue by CAM16. (roughly,
178
+ * hue 203, chroma 3, lightness 100)
179
+ */
180
+ class Cam16 {
181
+ /**
182
+ * All of the CAM16 dimensions can be calculated from 3 of the dimensions, in
183
+ * the following combinations:
184
+ * - {j or q} and {c, m, or s} and hue
185
+ * - jstar, astar, bstar
186
+ * Prefer using a static method that constructs from 3 of those dimensions.
187
+ * This constructor is intended for those methods to use to return all
188
+ * possible dimensions.
189
+ *
190
+ * @param hue
191
+ * @param chroma informally, colorfulness / color intensity. like saturation
192
+ * in HSL, except perceptually accurate.
193
+ * @param j lightness
194
+ * @param q brightness; ratio of lightness to white point's lightness
195
+ * @param m colorfulness
196
+ * @param s saturation; ratio of chroma to white point's chroma
197
+ * @param jstar CAM16-UCS J coordinate
198
+ * @param astar CAM16-UCS a coordinate
199
+ * @param bstar CAM16-UCS b coordinate
200
+ */
201
+ constructor(hue, chroma, j, q, m, s, jstar, astar, bstar) {
202
+ this.hue = hue;
203
+ this.chroma = chroma;
204
+ this.j = j;
205
+ this.q = q;
206
+ this.m = m;
207
+ this.s = s;
208
+ this.jstar = jstar;
209
+ this.astar = astar;
210
+ this.bstar = bstar;
211
+ }
212
+
213
+ /**
214
+ * CAM16 instances also have coordinates in the CAM16-UCS space, called J*,
215
+ * a*, b*, or jstar, astar, bstar in code. CAM16-UCS is included in the CAM16
216
+ * specification, and is used to measure distances between colors.
217
+ */
218
+ distance(other) {
219
+ const dJ = this.jstar - other.jstar;
220
+ const dA = this.astar - other.astar;
221
+ const dB = this.bstar - other.bstar;
222
+ const dEPrime = Math.sqrt(dJ * dJ + dA * dA + dB * dB);
223
+ const dE = 1.41 * Math.pow(dEPrime, 0.63);
224
+ return dE;
225
+ }
226
+
227
+ /**
228
+ * @param argb ARGB representation of a color.
229
+ * @return CAM16 color, assuming the color was viewed in default viewing
230
+ * conditions.
231
+ */
232
+ static fromInt(argb) {
233
+ return Cam16.fromIntInViewingConditions(argb, ViewingConditions.DEFAULT);
234
+ }
235
+
236
+ /**
237
+ * @param argb ARGB representation of a color.
238
+ * @param viewingConditions Information about the environment where the color
239
+ * was observed.
240
+ * @return CAM16 color.
241
+ */
242
+ static fromIntInViewingConditions(argb, viewingConditions) {
243
+ const red = (argb & 0x00ff0000) >> 16;
244
+ const green = (argb & 0x0000ff00) >> 8;
245
+ const blue = argb & 0x000000ff;
246
+ const redL = utils.linearized(red);
247
+ const greenL = utils.linearized(green);
248
+ const blueL = utils.linearized(blue);
249
+ const x = 0.41233895 * redL + 0.35762064 * greenL + 0.18051042 * blueL;
250
+ const y = 0.2126 * redL + 0.7152 * greenL + 0.0722 * blueL;
251
+ const z = 0.01932141 * redL + 0.11916382 * greenL + 0.95034478 * blueL;
252
+ const rC = 0.401288 * x + 0.650173 * y - 0.051461 * z;
253
+ const gC = -0.250268 * x + 1.204414 * y + 0.045854 * z;
254
+ const bC = -0.002079 * x + 0.048952 * y + 0.953127 * z;
255
+ const rD = viewingConditions.rgbD[0] * rC;
256
+ const gD = viewingConditions.rgbD[1] * gC;
257
+ const bD = viewingConditions.rgbD[2] * bC;
258
+ const rAF = Math.pow(viewingConditions.fl * Math.abs(rD) / 100.0, 0.42);
259
+ const gAF = Math.pow(viewingConditions.fl * Math.abs(gD) / 100.0, 0.42);
260
+ const bAF = Math.pow(viewingConditions.fl * Math.abs(bD) / 100.0, 0.42);
261
+ const rA = math.signum(rD) * 400.0 * rAF / (rAF + 27.13);
262
+ const gA = math.signum(gD) * 400.0 * gAF / (gAF + 27.13);
263
+ const bA = math.signum(bD) * 400.0 * bAF / (bAF + 27.13);
264
+ const a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
265
+ const b = (rA + gA - 2.0 * bA) / 9.0;
266
+ const u = (20.0 * rA + 20.0 * gA + 21.0 * bA) / 20.0;
267
+ const p2 = (40.0 * rA + 20.0 * gA + bA) / 20.0;
268
+ const atan2 = Math.atan2(b, a);
269
+ const atanDegrees = atan2 * 180.0 / Math.PI;
270
+ const hue = atanDegrees < 0 ? atanDegrees + 360.0 : atanDegrees >= 360 ? atanDegrees - 360.0 : atanDegrees;
271
+ const hueRadians = hue * Math.PI / 180.0;
272
+ const ac = p2 * viewingConditions.nbb;
273
+ const j = 100.0 * Math.pow(ac / viewingConditions.aw, viewingConditions.c * viewingConditions.z);
274
+ const q = 4.0 / viewingConditions.c * Math.sqrt(j / 100.0) * (viewingConditions.aw + 4.0) * viewingConditions.fLRoot;
275
+ const huePrime = hue < 20.14 ? hue + 360 : hue;
276
+ const eHue = 0.25 * (Math.cos(huePrime * Math.PI / 180.0 + 2.0) + 3.8);
277
+ const p1 = 50000.0 / 13.0 * eHue * viewingConditions.nc * viewingConditions.ncb;
278
+ const t = p1 * Math.sqrt(a * a + b * b) / (u + 0.305);
279
+ const alpha = Math.pow(t, 0.9) * Math.pow(1.64 - Math.pow(0.29, viewingConditions.n), 0.73);
280
+ const c = alpha * Math.sqrt(j / 100.0);
281
+ const m = c * viewingConditions.fLRoot;
282
+ const s = 50.0 * Math.sqrt(alpha * viewingConditions.c / (viewingConditions.aw + 4.0));
283
+ const jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j);
284
+ const mstar = 1.0 / 0.0228 * Math.log(1.0 + 0.0228 * m);
285
+ const astar = mstar * Math.cos(hueRadians);
286
+ const bstar = mstar * Math.sin(hueRadians);
287
+ return new Cam16(hue, c, j, q, m, s, jstar, astar, bstar);
288
+ }
289
+
290
+ /**
291
+ * @param j CAM16 lightness
292
+ * @param c CAM16 chroma
293
+ * @param h CAM16 hue
294
+ */
295
+ static fromJch(j, c, h) {
296
+ return Cam16.fromJchInViewingConditions(j, c, h, ViewingConditions.DEFAULT);
297
+ }
298
+
299
+ /**
300
+ * @param j CAM16 lightness
301
+ * @param c CAM16 chroma
302
+ * @param h CAM16 hue
303
+ * @param viewingConditions Information about the environment where the color
304
+ * was observed.
305
+ */
306
+ static fromJchInViewingConditions(j, c, h, viewingConditions) {
307
+ const q = 4.0 / viewingConditions.c * Math.sqrt(j / 100.0) * (viewingConditions.aw + 4.0) * viewingConditions.fLRoot;
308
+ const m = c * viewingConditions.fLRoot;
309
+ const alpha = c / Math.sqrt(j / 100.0);
310
+ const s = 50.0 * Math.sqrt(alpha * viewingConditions.c / (viewingConditions.aw + 4.0));
311
+ const hueRadians = h * Math.PI / 180.0;
312
+ const jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j);
313
+ const mstar = 1.0 / 0.0228 * Math.log(1.0 + 0.0228 * m);
314
+ const astar = mstar * Math.cos(hueRadians);
315
+ const bstar = mstar * Math.sin(hueRadians);
316
+ return new Cam16(h, c, j, q, m, s, jstar, astar, bstar);
317
+ }
318
+
319
+ /**
320
+ * @param jstar CAM16-UCS lightness.
321
+ * @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian
322
+ * coordinate on the Y axis.
323
+ * @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian
324
+ * coordinate on the X axis.
325
+ */
326
+ static fromUcs(jstar, astar, bstar) {
327
+ return Cam16.fromUcsInViewingConditions(jstar, astar, bstar, ViewingConditions.DEFAULT);
328
+ }
329
+
330
+ /**
331
+ * @param jstar CAM16-UCS lightness.
332
+ * @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian
333
+ * coordinate on the Y axis.
334
+ * @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian
335
+ * coordinate on the X axis.
336
+ * @param viewingConditions Information about the environment where the color
337
+ * was observed.
338
+ */
339
+ static fromUcsInViewingConditions(jstar, astar, bstar, viewingConditions) {
340
+ const a = astar;
341
+ const b = bstar;
342
+ const m = Math.sqrt(a * a + b * b);
343
+ const M = (Math.exp(m * 0.0228) - 1.0) / 0.0228;
344
+ const c = M / viewingConditions.fLRoot;
345
+ let h = Math.atan2(b, a) * (180.0 / Math.PI);
346
+ if (h < 0.0) {
347
+ h += 360.0;
348
+ }
349
+ const j = jstar / (1 - (jstar - 100) * 0.007);
350
+ return Cam16.fromJchInViewingConditions(j, c, h, viewingConditions);
351
+ }
352
+
353
+ /**
354
+ * @return ARGB representation of color, assuming the color was viewed in
355
+ * default viewing conditions, which are near-identical to the default
356
+ * viewing conditions for sRGB.
357
+ */
358
+ toInt() {
359
+ return this.viewed(ViewingConditions.DEFAULT);
360
+ }
361
+
362
+ /**
363
+ * @param viewingConditions Information about the environment where the color
364
+ * will be viewed.
365
+ * @return ARGB representation of color
366
+ */
367
+ viewed(viewingConditions) {
368
+ const alpha = this.chroma === 0.0 || this.j === 0.0 ? 0.0 : this.chroma / Math.sqrt(this.j / 100.0);
369
+ const t = Math.pow(alpha / Math.pow(1.64 - Math.pow(0.29, viewingConditions.n), 0.73), 1.0 / 0.9);
370
+ const hRad = this.hue * Math.PI / 180.0;
371
+ const eHue = 0.25 * (Math.cos(hRad + 2.0) + 3.8);
372
+ const ac = viewingConditions.aw * Math.pow(this.j / 100.0, 1.0 / viewingConditions.c / viewingConditions.z);
373
+ const p1 = eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb;
374
+ const p2 = ac / viewingConditions.nbb;
375
+ const hSin = Math.sin(hRad);
376
+ const hCos = Math.cos(hRad);
377
+ const gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11.0 * t * hCos + 108.0 * t * hSin);
378
+ const a = gamma * hCos;
379
+ const b = gamma * hSin;
380
+ const rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0;
381
+ const gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0;
382
+ const bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0;
383
+ const rCBase = Math.max(0, 27.13 * Math.abs(rA) / (400.0 - Math.abs(rA)));
384
+ const rC = math.signum(rA) * (100.0 / viewingConditions.fl) * Math.pow(rCBase, 1.0 / 0.42);
385
+ const gCBase = Math.max(0, 27.13 * Math.abs(gA) / (400.0 - Math.abs(gA)));
386
+ const gC = math.signum(gA) * (100.0 / viewingConditions.fl) * Math.pow(gCBase, 1.0 / 0.42);
387
+ const bCBase = Math.max(0, 27.13 * Math.abs(bA) / (400.0 - Math.abs(bA)));
388
+ const bC = math.signum(bA) * (100.0 / viewingConditions.fl) * Math.pow(bCBase, 1.0 / 0.42);
389
+ const rF = rC / viewingConditions.rgbD[0];
390
+ const gF = gC / viewingConditions.rgbD[1];
391
+ const bF = bC / viewingConditions.rgbD[2];
392
+ const x = 1.86206786 * rF - 1.01125463 * gF + 0.14918677 * bF;
393
+ const y = 0.38752654 * rF + 0.62144744 * gF - 0.00897398 * bF;
394
+ const z = -0.0158415 * rF - 0.03412294 * gF + 1.04996444 * bF;
395
+ const argb = utils.argbFromXyz(x, y, z);
396
+ return argb;
397
+ }
398
+
399
+ /// Given color expressed in XYZ and viewed in [viewingConditions], convert to
400
+ /// CAM16.
401
+ static fromXyzInViewingConditions(x, y, z, viewingConditions) {
402
+ // Transform XYZ to 'cone'/'rgb' responses
403
+
404
+ const rC = 0.401288 * x + 0.650173 * y - 0.051461 * z;
405
+ const gC = -0.250268 * x + 1.204414 * y + 0.045854 * z;
406
+ const bC = -0.002079 * x + 0.048952 * y + 0.953127 * z;
407
+
408
+ // Discount illuminant
409
+ const rD = viewingConditions.rgbD[0] * rC;
410
+ const gD = viewingConditions.rgbD[1] * gC;
411
+ const bD = viewingConditions.rgbD[2] * bC;
412
+
413
+ // chromatic adaptation
414
+ const rAF = Math.pow(viewingConditions.fl * Math.abs(rD) / 100.0, 0.42);
415
+ const gAF = Math.pow(viewingConditions.fl * Math.abs(gD) / 100.0, 0.42);
416
+ const bAF = Math.pow(viewingConditions.fl * Math.abs(bD) / 100.0, 0.42);
417
+ const rA = math.signum(rD) * 400.0 * rAF / (rAF + 27.13);
418
+ const gA = math.signum(gD) * 400.0 * gAF / (gAF + 27.13);
419
+ const bA = math.signum(bD) * 400.0 * bAF / (bAF + 27.13);
420
+
421
+ // redness-greenness
422
+ const a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
423
+ // yellowness-blueness
424
+ const b = (rA + gA - 2.0 * bA) / 9.0;
425
+
426
+ // auxiliary components
427
+ const u = (20.0 * rA + 20.0 * gA + 21.0 * bA) / 20.0;
428
+ const p2 = (40.0 * rA + 20.0 * gA + bA) / 20.0;
429
+
430
+ // hue
431
+ const atan2 = Math.atan2(b, a);
432
+ const atanDegrees = atan2 * 180.0 / Math.PI;
433
+ const hue = atanDegrees < 0 ? atanDegrees + 360.0 : atanDegrees >= 360 ? atanDegrees - 360 : atanDegrees;
434
+ const hueRadians = hue * Math.PI / 180.0;
435
+
436
+ // achromatic response to color
437
+ const ac = p2 * viewingConditions.nbb;
438
+
439
+ // CAM16 lightness and brightness
440
+ const J = 100.0 * Math.pow(ac / viewingConditions.aw, viewingConditions.c * viewingConditions.z);
441
+ const Q = 4.0 / viewingConditions.c * Math.sqrt(J / 100.0) * (viewingConditions.aw + 4.0) * viewingConditions.fLRoot;
442
+ const huePrime = hue < 20.14 ? hue + 360 : hue;
443
+ const eHue = 1.0 / 4.0 * (Math.cos(huePrime * Math.PI / 180.0 + 2.0) + 3.8);
444
+ const p1 = 50000.0 / 13.0 * eHue * viewingConditions.nc * viewingConditions.ncb;
445
+ const t = p1 * Math.sqrt(a * a + b * b) / (u + 0.305);
446
+ const alpha = Math.pow(t, 0.9) * Math.pow(1.64 - Math.pow(0.29, viewingConditions.n), 0.73);
447
+ // CAM16 chroma, colorfulness, chroma
448
+ const C = alpha * Math.sqrt(J / 100.0);
449
+ const M = C * viewingConditions.fLRoot;
450
+ const s = 50.0 * Math.sqrt(alpha * viewingConditions.c / (viewingConditions.aw + 4.0));
451
+
452
+ // CAM16-UCS components
453
+ const jstar = (1.0 + 100.0 * 0.007) * J / (1.0 + 0.007 * J);
454
+ const mstar = Math.log(1.0 + 0.0228 * M) / 0.0228;
455
+ const astar = mstar * Math.cos(hueRadians);
456
+ const bstar = mstar * Math.sin(hueRadians);
457
+ return new Cam16(hue, C, J, Q, M, s, jstar, astar, bstar);
458
+ }
459
+
460
+ /// XYZ representation of CAM16 seen in [viewingConditions].
461
+ xyzInViewingConditions(viewingConditions) {
462
+ const alpha = this.chroma === 0.0 || this.j === 0.0 ? 0.0 : this.chroma / Math.sqrt(this.j / 100.0);
463
+ const t = Math.pow(alpha / Math.pow(1.64 - Math.pow(0.29, viewingConditions.n), 0.73), 1.0 / 0.9);
464
+ const hRad = this.hue * Math.PI / 180.0;
465
+ const eHue = 0.25 * (Math.cos(hRad + 2.0) + 3.8);
466
+ const ac = viewingConditions.aw * Math.pow(this.j / 100.0, 1.0 / viewingConditions.c / viewingConditions.z);
467
+ const p1 = eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb;
468
+ const p2 = ac / viewingConditions.nbb;
469
+ const hSin = Math.sin(hRad);
470
+ const hCos = Math.cos(hRad);
471
+ const gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11 * t * hCos + 108.0 * t * hSin);
472
+ const a = gamma * hCos;
473
+ const b = gamma * hSin;
474
+ const rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0;
475
+ const gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0;
476
+ const bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0;
477
+ const rCBase = Math.max(0, 27.13 * Math.abs(rA) / (400.0 - Math.abs(rA)));
478
+ const rC = math.signum(rA) * (100.0 / viewingConditions.fl) * Math.pow(rCBase, 1.0 / 0.42);
479
+ const gCBase = Math.max(0, 27.13 * Math.abs(gA) / (400.0 - Math.abs(gA)));
480
+ const gC = math.signum(gA) * (100.0 / viewingConditions.fl) * Math.pow(gCBase, 1.0 / 0.42);
481
+ const bCBase = Math.max(0, 27.13 * Math.abs(bA) / (400.0 - Math.abs(bA)));
482
+ const bC = math.signum(bA) * (100.0 / viewingConditions.fl) * Math.pow(bCBase, 1.0 / 0.42);
483
+ const rF = rC / viewingConditions.rgbD[0];
484
+ const gF = gC / viewingConditions.rgbD[1];
485
+ const bF = bC / viewingConditions.rgbD[2];
486
+ const x = 1.86206786 * rF - 1.01125463 * gF + 0.14918677 * bF;
487
+ const y = 0.38752654 * rF + 0.62144744 * gF - 0.00897398 * bF;
488
+ const z = -0.0158415 * rF - 0.03412294 * gF + 1.04996444 * bF;
489
+ return [x, y, z];
490
+ }
491
+ }
492
+
493
+ // This file is automatically generated. Do not modify it.
494
+
495
+ // material_color_utilities is designed to have a consistent API across
496
+ // platforms and modular components that can be moved around easily. Using a
497
+ // class as a namespace facilitates this.
498
+ //
499
+ // tslint:disable:class-as-namespace
500
+ /**
501
+ * A class that solves the HCT equation.
502
+ */
503
+ class HctSolver {
504
+ /**
505
+ * Sanitizes a small enough angle in radians.
506
+ *
507
+ * @param angle An angle in radians; must not deviate too much
508
+ * from 0.
509
+ * @return A coterminal angle between 0 and 2pi.
510
+ */
511
+ static sanitizeRadians(angle) {
512
+ return (angle + Math.PI * 8) % (Math.PI * 2);
513
+ }
514
+
515
+ /**
516
+ * Delinearizes an RGB component, returning a floating-point
517
+ * number.
518
+ *
519
+ * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents
520
+ * linear R/G/B channel
521
+ * @return 0.0 <= output <= 255.0, color channel converted to
522
+ * regular RGB space
523
+ */
524
+ static trueDelinearized(rgbComponent) {
525
+ const normalized = rgbComponent / 100.0;
526
+ let delinearized = 0.0;
527
+ if (normalized <= 0.0031308) {
528
+ delinearized = normalized * 12.92;
529
+ } else {
530
+ delinearized = 1.055 * Math.pow(normalized, 1.0 / 2.4) - 0.055;
531
+ }
532
+ return delinearized * 255.0;
533
+ }
534
+ static chromaticAdaptation(component) {
535
+ const af = Math.pow(Math.abs(component), 0.42);
536
+ return math.signum(component) * 400.0 * af / (af + 27.13);
537
+ }
538
+
539
+ /**
540
+ * Returns the hue of a linear RGB color in CAM16.
541
+ *
542
+ * @param linrgb The linear RGB coordinates of a color.
543
+ * @return The hue of the color in CAM16, in radians.
544
+ */
545
+ static hueOf(linrgb) {
546
+ const scaledDiscount = math.matrixMultiply(linrgb, HctSolver.SCALED_DISCOUNT_FROM_LINRGB);
547
+ const rA = HctSolver.chromaticAdaptation(scaledDiscount[0]);
548
+ const gA = HctSolver.chromaticAdaptation(scaledDiscount[1]);
549
+ const bA = HctSolver.chromaticAdaptation(scaledDiscount[2]);
550
+ // redness-greenness
551
+ const a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
552
+ // yellowness-blueness
553
+ const b = (rA + gA - 2.0 * bA) / 9.0;
554
+ return Math.atan2(b, a);
555
+ }
556
+ static areInCyclicOrder(a, b, c) {
557
+ const deltaAB = HctSolver.sanitizeRadians(b - a);
558
+ const deltaAC = HctSolver.sanitizeRadians(c - a);
559
+ return deltaAB < deltaAC;
560
+ }
561
+
562
+ /**
563
+ * Solves the lerp equation.
564
+ *
565
+ * @param source The starting number.
566
+ * @param mid The number in the middle.
567
+ * @param target The ending number.
568
+ * @return A number t such that lerp(source, target, t) = mid.
569
+ */
570
+ static intercept(source, mid, target) {
571
+ return (mid - source) / (target - source);
572
+ }
573
+ static lerpPoint(source, t, target) {
574
+ return [source[0] + (target[0] - source[0]) * t, source[1] + (target[1] - source[1]) * t, source[2] + (target[2] - source[2]) * t];
575
+ }
576
+
577
+ /**
578
+ * Intersects a segment with a plane.
579
+ *
580
+ * @param source The coordinates of point A.
581
+ * @param coordinate The R-, G-, or B-coordinate of the plane.
582
+ * @param target The coordinates of point B.
583
+ * @param axis The axis the plane is perpendicular with. (0: R, 1:
584
+ * G, 2: B)
585
+ * @return The intersection point of the segment AB with the plane
586
+ * R=coordinate, G=coordinate, or B=coordinate
587
+ */
588
+ static setCoordinate(source, coordinate, target, axis) {
589
+ const t = HctSolver.intercept(source[axis], coordinate, target[axis]);
590
+ return HctSolver.lerpPoint(source, t, target);
591
+ }
592
+ static isBounded(x) {
593
+ return 0.0 <= x && x <= 100.0;
594
+ }
595
+
596
+ /**
597
+ * Returns the nth possible vertex of the polygonal intersection.
598
+ *
599
+ * @param y The Y value of the plane.
600
+ * @param n The zero-based index of the point. 0 <= n <= 11.
601
+ * @return The nth possible vertex of the polygonal intersection
602
+ * of the y plane and the RGB cube, in linear RGB coordinates, if
603
+ * it exists. If this possible vertex lies outside of the cube,
604
+ * [-1.0, -1.0, -1.0] is returned.
605
+ */
606
+ static nthVertex(y, n) {
607
+ const kR = HctSolver.Y_FROM_LINRGB[0];
608
+ const kG = HctSolver.Y_FROM_LINRGB[1];
609
+ const kB = HctSolver.Y_FROM_LINRGB[2];
610
+ const coordA = n % 4 <= 1 ? 0.0 : 100.0;
611
+ const coordB = n % 2 === 0 ? 0.0 : 100.0;
612
+ if (n < 4) {
613
+ const g = coordA;
614
+ const b = coordB;
615
+ const r = (y - g * kG - b * kB) / kR;
616
+ if (HctSolver.isBounded(r)) {
617
+ return [r, g, b];
618
+ } else {
619
+ return [-1.0, -1.0, -1.0];
620
+ }
621
+ } else if (n < 8) {
622
+ const b = coordA;
623
+ const r = coordB;
624
+ const g = (y - r * kR - b * kB) / kG;
625
+ if (HctSolver.isBounded(g)) {
626
+ return [r, g, b];
627
+ } else {
628
+ return [-1.0, -1.0, -1.0];
629
+ }
630
+ } else {
631
+ const r = coordA;
632
+ const g = coordB;
633
+ const b = (y - r * kR - g * kG) / kB;
634
+ if (HctSolver.isBounded(b)) {
635
+ return [r, g, b];
636
+ } else {
637
+ return [-1.0, -1.0, -1.0];
638
+ }
639
+ }
640
+ }
641
+
642
+ /**
643
+ * Finds the segment containing the desired color.
644
+ *
645
+ * @param y The Y value of the color.
646
+ * @param targetHue The hue of the color.
647
+ * @return A list of two sets of linear RGB coordinates, each
648
+ * corresponding to an endpoint of the segment containing the
649
+ * desired color.
650
+ */
651
+ static bisectToSegment(y, targetHue) {
652
+ let left = [-1.0, -1.0, -1.0];
653
+ let right = left;
654
+ let leftHue = 0.0;
655
+ let rightHue = 0.0;
656
+ let initialized = false;
657
+ let uncut = true;
658
+ for (let n = 0; n < 12; n++) {
659
+ const mid = HctSolver.nthVertex(y, n);
660
+ if (mid[0] < 0) {
661
+ continue;
662
+ }
663
+ const midHue = HctSolver.hueOf(mid);
664
+ if (!initialized) {
665
+ left = mid;
666
+ right = mid;
667
+ leftHue = midHue;
668
+ rightHue = midHue;
669
+ initialized = true;
670
+ continue;
671
+ }
672
+ if (uncut || HctSolver.areInCyclicOrder(leftHue, midHue, rightHue)) {
673
+ uncut = false;
674
+ if (HctSolver.areInCyclicOrder(leftHue, targetHue, midHue)) {
675
+ right = mid;
676
+ rightHue = midHue;
677
+ } else {
678
+ left = mid;
679
+ leftHue = midHue;
680
+ }
681
+ }
682
+ }
683
+ return [left, right];
684
+ }
685
+ static midpoint(a, b) {
686
+ return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2];
687
+ }
688
+ static criticalPlaneBelow(x) {
689
+ return Math.floor(x - 0.5);
690
+ }
691
+ static criticalPlaneAbove(x) {
692
+ return Math.ceil(x - 0.5);
693
+ }
694
+
695
+ /**
696
+ * Finds a color with the given Y and hue on the boundary of the
697
+ * cube.
698
+ *
699
+ * @param y The Y value of the color.
700
+ * @param targetHue The hue of the color.
701
+ * @return The desired color, in linear RGB coordinates.
702
+ */
703
+ static bisectToLimit(y, targetHue) {
704
+ const segment = HctSolver.bisectToSegment(y, targetHue);
705
+ let left = segment[0];
706
+ let leftHue = HctSolver.hueOf(left);
707
+ let right = segment[1];
708
+ for (let axis = 0; axis < 3; axis++) {
709
+ if (left[axis] !== right[axis]) {
710
+ let lPlane = -1;
711
+ let rPlane = 255;
712
+ if (left[axis] < right[axis]) {
713
+ lPlane = HctSolver.criticalPlaneBelow(HctSolver.trueDelinearized(left[axis]));
714
+ rPlane = HctSolver.criticalPlaneAbove(HctSolver.trueDelinearized(right[axis]));
715
+ } else {
716
+ lPlane = HctSolver.criticalPlaneAbove(HctSolver.trueDelinearized(left[axis]));
717
+ rPlane = HctSolver.criticalPlaneBelow(HctSolver.trueDelinearized(right[axis]));
718
+ }
719
+ for (let i = 0; i < 8; i++) {
720
+ if (Math.abs(rPlane - lPlane) <= 1) {
721
+ break;
722
+ } else {
723
+ const mPlane = Math.floor((lPlane + rPlane) / 2.0);
724
+ const midPlaneCoordinate = HctSolver.CRITICAL_PLANES[mPlane];
725
+ const mid = HctSolver.setCoordinate(left, midPlaneCoordinate, right, axis);
726
+ const midHue = HctSolver.hueOf(mid);
727
+ if (HctSolver.areInCyclicOrder(leftHue, targetHue, midHue)) {
728
+ right = mid;
729
+ rPlane = mPlane;
730
+ } else {
731
+ left = mid;
732
+ leftHue = midHue;
733
+ lPlane = mPlane;
734
+ }
735
+ }
736
+ }
737
+ }
738
+ }
739
+ return HctSolver.midpoint(left, right);
740
+ }
741
+ static inverseChromaticAdaptation(adapted) {
742
+ const adaptedAbs = Math.abs(adapted);
743
+ const base = Math.max(0, 27.13 * adaptedAbs / (400.0 - adaptedAbs));
744
+ return math.signum(adapted) * Math.pow(base, 1.0 / 0.42);
745
+ }
746
+
747
+ /**
748
+ * Finds a color with the given hue, chroma, and Y.
749
+ *
750
+ * @param hueRadians The desired hue in radians.
751
+ * @param chroma The desired chroma.
752
+ * @param y The desired Y.
753
+ * @return The desired color as a hexadecimal integer, if found; 0
754
+ * otherwise.
755
+ */
756
+ static findResultByJ(hueRadians, chroma, y) {
757
+ // Initial estimate of j.
758
+ let j = Math.sqrt(y) * 11.0;
759
+ // ===========================================================
760
+ // Operations inlined from Cam16 to avoid repeated calculation
761
+ // ===========================================================
762
+ const viewingConditions = ViewingConditions.DEFAULT;
763
+ const tInnerCoeff = 1 / Math.pow(1.64 - Math.pow(0.29, viewingConditions.n), 0.73);
764
+ const eHue = 0.25 * (Math.cos(hueRadians + 2.0) + 3.8);
765
+ const p1 = eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb;
766
+ const hSin = Math.sin(hueRadians);
767
+ const hCos = Math.cos(hueRadians);
768
+ for (let iterationRound = 0; iterationRound < 5; iterationRound++) {
769
+ // ===========================================================
770
+ // Operations inlined from Cam16 to avoid repeated calculation
771
+ // ===========================================================
772
+ const jNormalized = j / 100.0;
773
+ const alpha = chroma === 0.0 || j === 0.0 ? 0.0 : chroma / Math.sqrt(jNormalized);
774
+ const t = Math.pow(alpha * tInnerCoeff, 1.0 / 0.9);
775
+ const ac = viewingConditions.aw * Math.pow(jNormalized, 1.0 / viewingConditions.c / viewingConditions.z);
776
+ const p2 = ac / viewingConditions.nbb;
777
+ const gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11 * t * hCos + 108.0 * t * hSin);
778
+ const a = gamma * hCos;
779
+ const b = gamma * hSin;
780
+ const rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0;
781
+ const gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0;
782
+ const bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0;
783
+ const rCScaled = HctSolver.inverseChromaticAdaptation(rA);
784
+ const gCScaled = HctSolver.inverseChromaticAdaptation(gA);
785
+ const bCScaled = HctSolver.inverseChromaticAdaptation(bA);
786
+ const linrgb = math.matrixMultiply([rCScaled, gCScaled, bCScaled], HctSolver.LINRGB_FROM_SCALED_DISCOUNT);
787
+ // ===========================================================
788
+ // Operations inlined from Cam16 to avoid repeated calculation
789
+ // ===========================================================
790
+ if (linrgb[0] < 0 || linrgb[1] < 0 || linrgb[2] < 0) {
791
+ return 0;
792
+ }
793
+ const kR = HctSolver.Y_FROM_LINRGB[0];
794
+ const kG = HctSolver.Y_FROM_LINRGB[1];
795
+ const kB = HctSolver.Y_FROM_LINRGB[2];
796
+ const fnj = kR * linrgb[0] + kG * linrgb[1] + kB * linrgb[2];
797
+ if (fnj <= 0) {
798
+ return 0;
799
+ }
800
+ if (iterationRound === 4 || Math.abs(fnj - y) < 0.002) {
801
+ if (linrgb[0] > 100.01 || linrgb[1] > 100.01 || linrgb[2] > 100.01) {
802
+ return 0;
803
+ }
804
+ return utils.argbFromLinrgb(linrgb);
805
+ }
806
+ // Iterates with Newton method,
807
+ // Using 2 * fn(j) / j as the approximation of fn'(j)
808
+ j = j - (fnj - y) * j / (2 * fnj);
809
+ }
810
+ return 0;
811
+ }
812
+
813
+ /**
814
+ * Finds an sRGB color with the given hue, chroma, and L*, if
815
+ * possible.
816
+ *
817
+ * @param hueDegrees The desired hue, in degrees.
818
+ * @param chroma The desired chroma.
819
+ * @param lstar The desired L*.
820
+ * @return A hexadecimal representing the sRGB color. The color
821
+ * has sufficiently close hue, chroma, and L* to the desired
822
+ * values, if possible; otherwise, the hue and L* will be
823
+ * sufficiently close, and chroma will be maximized.
824
+ */
825
+ static solveToInt(hueDegrees, chroma, lstar) {
826
+ if (chroma < 0.0001 || lstar < 0.0001 || lstar > 99.9999) {
827
+ return utils.argbFromLstar(lstar);
828
+ }
829
+ hueDegrees = math.sanitizeDegreesDouble(hueDegrees);
830
+ const hueRadians = hueDegrees / 180 * Math.PI;
831
+ const y = utils.yFromLstar(lstar);
832
+ const exactAnswer = HctSolver.findResultByJ(hueRadians, chroma, y);
833
+ if (exactAnswer !== 0) {
834
+ return exactAnswer;
835
+ }
836
+ const linrgb = HctSolver.bisectToLimit(y, hueRadians);
837
+ return utils.argbFromLinrgb(linrgb);
838
+ }
839
+
840
+ /**
841
+ * Finds an sRGB color with the given hue, chroma, and L*, if
842
+ * possible.
843
+ *
844
+ * @param hueDegrees The desired hue, in degrees.
845
+ * @param chroma The desired chroma.
846
+ * @param lstar The desired L*.
847
+ * @return An CAM16 object representing the sRGB color. The color
848
+ * has sufficiently close hue, chroma, and L* to the desired
849
+ * values, if possible; otherwise, the hue and L* will be
850
+ * sufficiently close, and chroma will be maximized.
851
+ */
852
+ static solveToCam(hueDegrees, chroma, lstar) {
853
+ return Cam16.fromInt(HctSolver.solveToInt(hueDegrees, chroma, lstar));
854
+ }
855
+ }
856
+ _defineProperty(HctSolver, "SCALED_DISCOUNT_FROM_LINRGB", [[0.001200833568784504, 0.002389694492170889, 0.0002795742885861124], [0.0005891086651375999, 0.0029785502573438758, 0.0003270666104008398], [0.00010146692491640572, 0.0005364214359186694, 0.0032979401770712076]]);
857
+ _defineProperty(HctSolver, "LINRGB_FROM_SCALED_DISCOUNT", [[1373.2198709594231, -1100.4251190754821, -7.278681089101213], [-271.815969077903, 559.6580465940733, -32.46047482791194], [1.9622899599665666, -57.173814538844006, 308.7233197812385]]);
858
+ _defineProperty(HctSolver, "Y_FROM_LINRGB", [0.2126, 0.7152, 0.0722]);
859
+ _defineProperty(HctSolver, "CRITICAL_PLANES", [0.015176349177441876, 0.045529047532325624, 0.07588174588720938, 0.10623444424209313, 0.13658714259697685, 0.16693984095186062, 0.19729253930674434, 0.2276452376616281, 0.2579979360165119, 0.28835063437139563, 0.3188300904430532, 0.350925934958123, 0.3848314933096426, 0.42057480301049466, 0.458183274052838, 0.4976837250274023, 0.5391024159806381, 0.5824650784040898, 0.6277969426914107, 0.6751227633498623, 0.7244668422128921, 0.775853049866786, 0.829304845476233, 0.8848452951698498, 0.942497089126609, 1.0022825574869039, 1.0642236851973577, 1.1283421258858297, 1.1946592148522128, 1.2631959812511864, 1.3339731595349034, 1.407011200216447, 1.4823302800086415, 1.5599503113873272, 1.6398909516233677, 1.7221716113234105, 1.8068114625156377, 1.8938294463134073, 1.9832442801866852, 2.075074464868551, 2.1693382909216234, 2.2660538449872063, 2.36523901573795, 2.4669114995532007, 2.5710888059345764, 2.6777882626779785, 2.7870270208169257, 2.898822059350997, 3.0131901897720907, 3.1301480604002863, 3.2497121605402226, 3.3718988244681087, 3.4967242352587946, 3.624204428461639, 3.754355295633311, 3.887192587735158, 4.022731918402185, 4.160988767090289, 4.301978482107941, 4.445716283538092, 4.592217266055746, 4.741496401646282, 4.893568542229298, 5.048448422192488, 5.20615066083972, 5.3666897647573375, 5.5300801301023865, 5.696336044816294, 5.865471690767354, 6.037501145825082, 6.212438385869475, 6.390297286737924, 6.571091626112461, 6.7548350853498045, 6.941541251256611, 7.131223617812143, 7.323895587840543, 7.5195704746346665, 7.7182615035334345, 7.919981813454504, 8.124744458384042, 8.332562408825165, 8.543448553206703, 8.757415699253682, 8.974476575321063, 9.194643831691977, 9.417930041841839, 9.644347703669503, 9.873909240696694, 10.106627003236781, 10.342513269534024, 10.58158024687427, 10.8238400726681, 11.069304815507364, 11.317986476196008, 11.569896988756009, 11.825048221409341, 12.083451977536606, 12.345119996613247, 12.610063955123938, 12.878295467455942, 13.149826086772048, 13.42466730586372, 13.702830557985108, 13.984327217668513, 14.269168601521828, 14.55736596900856, 14.848930523210871, 15.143873411576273, 15.44220572664832, 15.743938506781891, 16.04908273684337, 16.35764934889634, 16.66964922287304, 16.985093187232053, 17.30399201960269, 17.62635644741625, 17.95219714852476, 18.281524751807332, 18.614349837764564, 18.95068293910138, 19.290534541298456, 19.633915083172692, 19.98083495742689, 20.331304511189067, 20.685334046541502, 21.042933821039977, 21.404114048223256, 21.76888489811322, 22.137256497705877, 22.50923893145328, 22.884842241736916, 23.264076429332462, 23.6469514538663, 24.033477234264016, 24.42366364919083, 24.817520537484558, 25.21505769858089, 25.61628489293138, 26.021211842414342, 26.429848230738664, 26.842203703840827, 27.258287870275353, 27.678110301598522, 28.10168053274597, 28.529008062403893, 28.96010235337422, 29.39497283293396, 29.83362889318845, 30.276079891419332, 30.722335150426627, 31.172403958865512, 31.62629557157785, 32.08401920991837, 32.54558406207592, 33.010999283389665, 33.4802739966603, 33.953417292456834, 34.430438229418264, 34.911345834551085, 35.39614910352207, 35.88485700094671, 36.37747846067349, 36.87402238606382, 37.37449765026789, 37.87891309649659, 38.38727753828926, 38.89959975977785, 39.41588851594697, 39.93615253289054, 40.460400508064545, 40.98864111053629, 41.520882981230194, 42.05713473317016, 42.597404951718396, 43.141702194811224, 43.6900349931913, 44.24241185063697, 44.798841244188324, 45.35933162437017, 45.92389141541209, 46.49252901546552, 47.065252796817916, 47.64207110610409, 48.22299226451468, 48.808024568002054, 49.3971762874833, 49.9904556690408, 50.587870934119984, 51.189430279724725, 51.79514187861014, 52.40501387947288, 53.0190544071392, 53.637271562750364, 54.259673423945976, 54.88626804504493, 55.517063457223934, 56.15206766869424, 56.79128866487574, 57.43473440856916, 58.08241284012621, 58.734331877617365, 59.39049941699807, 60.05092333227251, 60.715611475655585, 61.38457167773311, 62.057811747619894, 62.7353394731159, 63.417162620860914, 64.10328893648692, 64.79372614476921, 65.48848194977529, 66.18756403501224, 66.89098006357258, 67.59873767827808, 68.31084450182222, 69.02730813691093, 69.74813616640164, 70.47333615344107, 71.20291564160104, 71.93688215501312, 72.67524319850172, 73.41800625771542, 74.16517879925733, 74.9167682708136, 75.67278210128072, 76.43322770089146, 77.1981124613393, 77.96744375590167, 78.74122893956174, 79.51947534912904, 80.30219030335869, 81.08938110306934, 81.88105503125999, 82.67721935322541, 83.4778813166706, 84.28304815182372, 85.09272707154808, 85.90692527145302, 86.72564993000343, 87.54890820862819, 88.3767072518277, 89.2090541872801, 90.04595612594655, 90.88742016217518, 91.73345337380438, 92.58406282226491, 93.43925555268066, 94.29903859396902, 95.16341895893969, 96.03240364439274, 96.9059996312159, 97.78421388448044, 98.6670533535366, 99.55452497210776]);
860
+ export class ViewingConditions {
861
+ /**
862
+ * Create ViewingConditions from a simple, physically relevant, set of
863
+ * parameters.
864
+ *
865
+ * @param whitePoint White point, measured in the XYZ color space.
866
+ * default = D65, or sunny day afternoon
867
+ * @param adaptingLuminance The luminance of the adapting field. Informally,
868
+ * how bright it is in the room where the color is viewed. Can be
869
+ * calculated from lux by multiplying lux by 0.0586. default = 11.72,
870
+ * or 200 lux.
871
+ * @param backgroundLstar The lightness of the area surrounding the color.
872
+ * measured by L* in L*a*b*. default = 50.0
873
+ * @param surround A general description of the lighting surrounding the
874
+ * color. 0 is pitch dark, like watching a movie in a theater. 1.0 is a
875
+ * dimly light room, like watching TV at home at night. 2.0 means there
876
+ * is no difference between the lighting on the color and around it.
877
+ * default = 2.0
878
+ * @param discountingIlluminant Whether the eye accounts for the tint of the
879
+ * ambient lighting, such as knowing an apple is still red in green light.
880
+ * default = false, the eye does not perform this process on
881
+ * self-luminous objects like displays.
882
+ */
883
+ static make(whitePoint = utils.whitePointD65(), adaptingLuminance = 200.0 / Math.PI * utils.yFromLstar(50.0) / 100.0, backgroundLstar = 50.0, surround = 2.0, discountingIlluminant = false) {
884
+ const xyz = whitePoint;
885
+ const rW = xyz[0] * 0.401288 + xyz[1] * 0.650173 + xyz[2] * -0.051461;
886
+ const gW = xyz[0] * -0.250268 + xyz[1] * 1.204414 + xyz[2] * 0.045854;
887
+ const bW = xyz[0] * -0.002079 + xyz[1] * 0.048952 + xyz[2] * 0.953127;
888
+ const f = 0.8 + surround / 10.0;
889
+ const c = f >= 0.9 ? math.lerp(0.59, 0.69, (f - 0.9) * 10.0) : math.lerp(0.525, 0.59, (f - 0.8) * 10.0);
890
+ let d = discountingIlluminant ? 1.0 : f * (1.0 - 1.0 / 3.6 * Math.exp((-adaptingLuminance - 42.0) / 92.0));
891
+ d = d > 1.0 ? 1.0 : d < 0.0 ? 0.0 : d;
892
+ const nc = f;
893
+ const rgbD = [d * (100.0 / rW) + 1.0 - d, d * (100.0 / gW) + 1.0 - d, d * (100.0 / bW) + 1.0 - d];
894
+ const k = 1.0 / (5.0 * adaptingLuminance + 1.0);
895
+ const k4 = k * k * k * k;
896
+ const k4F = 1.0 - k4;
897
+ const fl = k4 * adaptingLuminance + 0.1 * k4F * k4F * Math.cbrt(5.0 * adaptingLuminance);
898
+ const n = utils.yFromLstar(backgroundLstar) / whitePoint[1];
899
+ const z = 1.48 + Math.sqrt(n);
900
+ const nbb = 0.725 / Math.pow(n, 0.2);
901
+ const ncb = nbb;
902
+ const rgbAFactors = [Math.pow(fl * rgbD[0] * rW / 100.0, 0.42), Math.pow(fl * rgbD[1] * gW / 100.0, 0.42), Math.pow(fl * rgbD[2] * bW / 100.0, 0.42)];
903
+ const rgbA = [400.0 * rgbAFactors[0] / (rgbAFactors[0] + 27.13), 400.0 * rgbAFactors[1] / (rgbAFactors[1] + 27.13), 400.0 * rgbAFactors[2] / (rgbAFactors[2] + 27.13)];
904
+ const aw = (2.0 * rgbA[0] + rgbA[1] + 0.05 * rgbA[2]) * nbb;
905
+ return new ViewingConditions(n, aw, nbb, ncb, c, nc, rgbD, fl, Math.pow(fl, 0.25), z);
906
+ }
907
+
908
+ /**
909
+ * Parameters are intermediate values of the CAM16 conversion process. Their
910
+ * names are shorthand for technical color science terminology, this class
911
+ * would not benefit from documenting them individually. A brief overview
912
+ * is available in the CAM16 specification, and a complete overview requires
913
+ * a color science textbook, such as Fairchild's Color Appearance Models.
914
+ */
915
+ constructor(n, aw, nbb, ncb, c, nc, rgbD, fl, fLRoot, z) {
916
+ this.n = n;
917
+ this.aw = aw;
918
+ this.nbb = nbb;
919
+ this.ncb = ncb;
920
+ this.c = c;
921
+ this.nc = nc;
922
+ this.rgbD = rgbD;
923
+ this.fl = fl;
924
+ this.fLRoot = fLRoot;
925
+ this.z = z;
926
+ }
927
+ }
928
+ /**
929
+ * sRGB-like viewing conditions.
930
+ */
931
+ _defineProperty(ViewingConditions, "DEFAULT", ViewingConditions.make());