Skip to content

Commit 2c847ba

Browse files
committed
Website updates
1 parent 4fe61d8 commit 2c847ba

File tree

17 files changed

+193
-58
lines changed

17 files changed

+193
-58
lines changed

dist/en/main/apidoc/module-ol_color.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ <h4 class="name">
189189

190190
<div class="tag-source">
191191
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js">color.js</a>,
192-
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js#L135">line 135</a>
192+
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js#L294">line 294</a>
193193
</div>
194194

195195
</div>
@@ -331,7 +331,7 @@ <h4 class="name">
331331

332332
<div class="tag-source">
333333
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js">color.js</a>,
334-
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js#L32">line 32</a>
334+
<a href="https://github.com/openlayers/openlayers/blob/main/src/ol/color.js#L135">line 135</a>
335335
</div>
336336

337337
</div>

dist/en/main/examples/common.js

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/examples/common.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/examples/export-map.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/examples/offscreen-canvas.worker.worker.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/examples/offscreen-canvas.worker.worker.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/ol/color.d.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ export function fromString(s: string): Color;
3535
* @api
3636
*/
3737
export function asArray(color: Color | string): Color;
38-
/**
39-
* Exported for the tests.
40-
* @param {Color} color Color.
41-
* @return {Color} Clamped color.
42-
*/
43-
export function normalize(color: Color): Color;
4438
/**
4539
* @param {Color} color Color.
4640
* @return {string} String.

dist/en/main/ol/color.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/en/main/ol/color.js

Lines changed: 173 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
/**
22
* @module ol/color
33
*/
4-
import parseRgba from 'color-rgba';
5-
import lchuv from 'color-space/lchuv.js';
6-
import rgb from 'color-space/rgb.js';
7-
import xyz from 'color-space/xyz.js';
8-
import {clamp} from './math.js';
4+
import {createCanvasContext2D} from './dom.js';
5+
import {clamp, toFixed} from './math.js';
96

107
/**
118
* A color represented as a short array [red, green, blue, alpha].
@@ -23,6 +20,112 @@ import {clamp} from './math.js';
2320
*/
2421
export const NO_COLOR = [NaN, NaN, NaN, 0];
2522

23+
let colorParseContext;
24+
/**
25+
* @return {CanvasRenderingContext2D} The color parse context
26+
*/
27+
function getColorParseContext() {
28+
if (!colorParseContext) {
29+
colorParseContext = createCanvasContext2D(1, 1, undefined, {
30+
willReadFrequently: true,
31+
desynchronized: true,
32+
});
33+
}
34+
return colorParseContext;
35+
}
36+
37+
const rgbModernRegEx =
38+
/^rgba?\(\s*(\d+%?)\s+(\d+%?)\s+(\d+%?)(?:\s*\/\s*(\d+%|\d*\.\d+|[01]))?\s*\)$/i;
39+
const rgbLegacyAbsoluteRegEx =
40+
/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*(\d+%|\d*\.\d+|[01]))?\s*\)$/i;
41+
const rgbLegacyPercentageRegEx =
42+
/^rgba?\(\s*(\d+%)\s*,\s*(\d+%)\s*,\s*(\d+%)(?:\s*,\s*(\d+%|\d*\.\d+|[01]))?\s*\)$/i;
43+
const hexRegEx = /^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i;
44+
45+
/**
46+
* @param {string} s Color component as number or percentage.
47+
* @param {number} divider Divider for percentage.
48+
* @return {number} Color component.
49+
*/
50+
function toColorComponent(s, divider) {
51+
return s.endsWith('%')
52+
? Number(s.substring(0, s.length - 1)) / divider
53+
: Number(s);
54+
}
55+
56+
/**
57+
* @param {string} color Color string.
58+
*/
59+
function throwInvalidColor(color) {
60+
throw new Error('failed to parse "' + color + '" as color');
61+
}
62+
63+
/**
64+
* @param {string} color Color string.
65+
* @return {Color} RGBa color array.
66+
*/
67+
function parseRgba(color) {
68+
// Fast lane for rgb(a) colors
69+
if (color.toLowerCase().startsWith('rgb')) {
70+
const rgb =
71+
color.match(rgbLegacyAbsoluteRegEx) ||
72+
color.match(rgbModernRegEx) ||
73+
color.match(rgbLegacyPercentageRegEx);
74+
if (rgb) {
75+
const alpha = rgb[4];
76+
const rgbDivider = 100 / 255;
77+
return [
78+
clamp((toColorComponent(rgb[1], rgbDivider) + 0.5) | 0, 0, 255),
79+
clamp((toColorComponent(rgb[2], rgbDivider) + 0.5) | 0, 0, 255),
80+
clamp((toColorComponent(rgb[3], rgbDivider) + 0.5) | 0, 0, 255),
81+
alpha !== undefined ? clamp(toColorComponent(alpha, 100), 0, 1) : 1,
82+
];
83+
}
84+
throwInvalidColor(color);
85+
}
86+
// Fast lane for hex colors (also with alpha)
87+
if (color.startsWith('#')) {
88+
if (hexRegEx.test(color)) {
89+
const hex = color.substring(1);
90+
const step = hex.length <= 4 ? 1 : 2;
91+
const colorFromHex = [0, 0, 0, 255];
92+
for (let i = 0, ii = hex.length; i < ii; i += step) {
93+
let colorComponent = parseInt(hex.substring(i, i + step), 16);
94+
if (step === 1) {
95+
colorComponent += colorComponent << 4;
96+
}
97+
colorFromHex[i / step] = colorComponent;
98+
}
99+
colorFromHex[3] = colorFromHex[3] / 255;
100+
return colorFromHex;
101+
}
102+
throwInvalidColor(color);
103+
}
104+
// Use canvas color serialization to parse the color into hex or rgba
105+
// See https://www.w3.org/TR/2021/SPSD-2dcontext-20210128/#serialization-of-a-color
106+
const context = getColorParseContext();
107+
context.fillStyle = '#abcdef';
108+
let invalidCheckFillStyle = context.fillStyle;
109+
context.fillStyle = color;
110+
if (context.fillStyle === invalidCheckFillStyle) {
111+
context.fillStyle = '#fedcba';
112+
invalidCheckFillStyle = context.fillStyle;
113+
context.fillStyle = color;
114+
if (context.fillStyle === invalidCheckFillStyle) {
115+
throwInvalidColor(color);
116+
}
117+
}
118+
const colorString = context.fillStyle;
119+
if (colorString.startsWith('#') || colorString.startsWith('rgba')) {
120+
return parseRgba(colorString);
121+
}
122+
context.clearRect(0, 0, 1, 1);
123+
context.fillRect(0, 0, 1, 1);
124+
const colorFromImage = Array.from(context.getImageData(0, 0, 1, 1).data);
125+
colorFromImage[3] = toFixed(colorFromImage[3] / 255, 3);
126+
return colorFromImage;
127+
}
128+
26129
/**
27130
* Return the color as an rgba string.
28131
* @param {Color|string} color Color.
@@ -69,24 +172,81 @@ export function withAlpha(color) {
69172
return output;
70173
}
71174

175+
// The functions b1, b2, a1, a2, rgbaToLcha and lchaToRgba below are adapted from
176+
// https://stackoverflow.com/a/67219995/2389327
177+
178+
/**
179+
* @param {number} v Input value.
180+
* @return {number} Output value.
181+
*/
182+
function b1(v) {
183+
return v > 0.0031308 ? Math.pow(v, 1 / 2.4) * 269.025 - 14.025 : v * 3294.6;
184+
}
185+
186+
/**
187+
* @param {number} v Input value.
188+
* @return {number} Output value.
189+
*/
190+
function b2(v) {
191+
return v > 0.2068965 ? Math.pow(v, 3) : (v - 4 / 29) * (108 / 841);
192+
}
193+
194+
/**
195+
* @param {number} v Input value.
196+
* @return {number} Output value.
197+
*/
198+
function a1(v) {
199+
return v > 10.314724 ? Math.pow((v + 14.025) / 269.025, 2.4) : v / 3294.6;
200+
}
201+
202+
/**
203+
* @param {number} v Input value.
204+
* @return {number} Output value.
205+
*/
206+
function a2(v) {
207+
return v > 0.0088564 ? Math.pow(v, 1 / 3) : v / (108 / 841) + 4 / 29;
208+
}
209+
72210
/**
73211
* @param {Color} color RGBA color.
74212
* @return {Color} LCHuv color with alpha.
75213
*/
76214
export function rgbaToLcha(color) {
77-
const output = xyz.lchuv(rgb.xyz(color));
78-
output[3] = color[3];
79-
return output;
215+
const r = a1(color[0]);
216+
const g = a1(color[1]);
217+
const b = a1(color[2]);
218+
const y = a2(r * 0.222488403 + g * 0.716873169 + b * 0.06060791);
219+
const l = 500 * (a2(r * 0.452247074 + g * 0.399439023 + b * 0.148375274) - y);
220+
const q = 200 * (y - a2(r * 0.016863605 + g * 0.117638439 + b * 0.865350722));
221+
const h = Math.atan2(q, l) * (180 / Math.PI);
222+
return [
223+
116 * y - 16,
224+
Math.sqrt(l * l + q * q),
225+
h < 0 ? h + 360 : h,
226+
color[3],
227+
];
80228
}
81229

82230
/**
83231
* @param {Color} color LCHuv color with alpha.
84232
* @return {Color} RGBA color.
85233
*/
86234
export function lchaToRgba(color) {
87-
const output = xyz.rgb(lchuv.xyz(color));
88-
output[3] = color[3];
89-
return output;
235+
const l = (color[0] + 16) / 116;
236+
const c = color[1];
237+
const h = (color[2] * Math.PI) / 180;
238+
const y = b2(l);
239+
const x = b2(l + (c / 500) * Math.cos(h));
240+
const z = b2(l - (c / 200) * Math.sin(h));
241+
const r = b1(x * 3.021973625 - y * 1.617392459 - z * 0.404875592);
242+
const g = b1(x * -0.943766287 + y * 1.916279586 + z * 0.027607165);
243+
const b = b1(x * 0.069407491 - y * 0.22898585 + z * 1.159737864);
244+
return [
245+
clamp((r + 0.5) | 0, 0, 255),
246+
clamp((g + 0.5) | 0, 0, 255),
247+
clamp((b + 0.5) | 0, 0, 255),
248+
color[3],
249+
];
90250
}
91251

92252
/**
@@ -112,14 +272,13 @@ export function fromString(s) {
112272

113273
const color = parseRgba(s);
114274
if (color.length !== 4) {
115-
throw new Error('failed to parse "' + s + '" as color');
275+
throwInvalidColor(s);
116276
}
117277
for (const c of color) {
118278
if (isNaN(c)) {
119-
throw new Error('failed to parse "' + s + '" as color');
279+
throwInvalidColor(s);
120280
}
121281
}
122-
normalize(color);
123282
cache[s] = color;
124283
++cacheSize;
125284
return color;
@@ -139,19 +298,6 @@ export function asArray(color) {
139298
return fromString(color);
140299
}
141300

142-
/**
143-
* Exported for the tests.
144-
* @param {Color} color Color.
145-
* @return {Color} Clamped color.
146-
*/
147-
export function normalize(color) {
148-
color[0] = clamp((color[0] + 0.5) | 0, 0, 255);
149-
color[1] = clamp((color[1] + 0.5) | 0, 0, 255);
150-
color[2] = clamp((color[2] + 0.5) | 0, 0, 255);
151-
color[3] = clamp(color[3], 0, 1);
152-
return color;
153-
}
154-
155301
/**
156302
* @param {Color} color Color.
157303
* @return {string} String.

dist/en/main/ol/dist/ol.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ declare namespace ol {
4848
export { _ol_color$fromString as fromString };
4949
export { _ol_color$isStringColor as isStringColor };
5050
export { _ol_color$lchaToRgba as lchaToRgba };
51-
export { _ol_color$normalize as normalize };
5251
export { _ol_color$rgbaToLcha as rgbaToLcha };
5352
export { _ol_color$toString as toString };
5453
export { _ol_color$withAlpha as withAlpha };
@@ -1065,7 +1064,6 @@ import { asString as _ol_color$asString } from '../../ol/color.js';
10651064
import { fromString as _ol_color$fromString } from '../../ol/color.js';
10661065
import { isStringColor as _ol_color$isStringColor } from '../../ol/color.js';
10671066
import { lchaToRgba as _ol_color$lchaToRgba } from '../../ol/color.js';
1068-
import { normalize as _ol_color$normalize } from '../../ol/color.js';
10691067
import { rgbaToLcha as _ol_color$rgbaToLcha } from '../../ol/color.js';
10701068
import { toString as _ol_color$toString } from '../../ol/color.js';
10711069
import { withAlpha as _ol_color$withAlpha } from '../../ol/color.js';

0 commit comments

Comments
 (0)