Browse Source

Removes Color namespaces

main
Eric Amodio 1 year ago
parent
commit
cff094a3e2
2 changed files with 227 additions and 283 deletions
  1. +24
    -0
      src/constants.ts
  2. +203
    -283
      src/system/color.ts

+ 24
- 0
src/constants.ts View File

@ -13,16 +13,40 @@ export const ImageMimetypes: Record = {
export const enum CharCode {
/**
* The `#` character.
*/
Hash = 35,
/**
* The `/` character.
*/
Slash = 47,
Digit0 = 48,
Digit1 = 49,
Digit2 = 50,
Digit3 = 51,
Digit4 = 52,
Digit5 = 53,
Digit6 = 54,
Digit7 = 55,
Digit8 = 56,
Digit9 = 57,
/**
* The `\` character.
*/
Backslash = 92,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
Z = 90,
a = 97,
b = 98,
c = 99,
d = 100,
e = 101,
f = 102,
z = 122,
}

+ 203
- 283
src/system/color.ts View File

@ -1,3 +1,5 @@
import { CharCode } from '../constants';
const cssColorRegex =
/^(?:(#?)([0-9a-f]{3}|[0-9a-f]{6})|((?:rgb|hsl)a?)\((-?\d+%?)[,\s]+(-?\d+%?)[,\s]+(-?\d+%?)[,\s]*(-?[\d.]+%?)?\))$/i;
@ -95,75 +97,6 @@ export function toRgba(color: string) {
}
}
const enum CharCode {
/**
* The `#` character.
*/
Hash = 35,
Digit0 = 48,
Digit1 = 49,
Digit2 = 50,
Digit3 = 51,
Digit4 = 52,
Digit5 = 53,
Digit6 = 54,
Digit7 = 55,
Digit8 = 56,
Digit9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
a = 97,
b = 98,
c = 99,
d = 100,
e = 101,
f = 102,
g = 103,
h = 104,
i = 105,
j = 106,
k = 107,
l = 108,
m = 109,
n = 110,
o = 111,
p = 112,
q = 113,
r = 114,
s = 115,
t = 116,
u = 117,
v = 118,
w = 119,
x = 120,
y = 121,
z = 122,
}
function mixColors(col1: Color, col2: Color, factor: number): Color {
const xyz0 = col1.rgba;
const xyz1 = col2.rgba;
@ -465,13 +398,13 @@ export class HSVA {
export class Color {
static fromHex(hex: string): Color {
return Color.Format.CSS.parseHex(hex) || Color.red;
return parseHex(hex) || Color.red;
}
static from(value: string | Color): Color {
if (value instanceof Color) return value;
return Color.Format.CSS.parseString(value) || Color.red;
return parseString(value) || Color.red;
}
static equals(a: Color | null, b: Color | null): boolean {
@ -678,7 +611,7 @@ export class Color {
private _toString?: string;
toString(): string {
if (!this._toString) {
this._toString = Color.Format.CSS.format(this);
this._toString = format(this);
}
return this._toString;
}
@ -715,229 +648,216 @@ export class Color {
static readonly transparent = new Color(new RGBA(0, 0, 0, 0));
}
export namespace Color {
export namespace Format {
export namespace CSS {
export function formatRGB(color: Color): string {
if (color.rgba.a === 1) {
return `rgb(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b})`;
}
export function formatRGB(color: Color): string {
if (color.rgba.a === 1) {
return `rgb(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b})`;
}
return Color.Format.CSS.formatRGBA(color);
}
return formatRGBA(color);
}
export function formatRGBA(color: Color): string {
return `rgba(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b}, ${Number(color.rgba.a.toFixed(2))})`;
}
export function formatRGBA(color: Color): string {
return `rgba(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b}, ${Number(color.rgba.a.toFixed(2))})`;
}
export function formatHSL(color: Color): string {
if (color.hsla.a === 1) {
return `hsl(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(
2,
)}%)`;
}
export function formatHSL(color: Color): string {
if (color.hsla.a === 1) {
return `hsl(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(2)}%)`;
}
return Color.Format.CSS.formatHSLA(color);
}
return formatHSLA(color);
}
export function formatHSLA(color: Color): string {
return `hsla(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(
2,
)}%, ${color.hsla.a.toFixed(2)})`;
}
export function formatHSLA(color: Color): string {
return `hsla(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(
2,
)}%, ${color.hsla.a.toFixed(2)})`;
}
function _toTwoDigitHex(n: number): string {
const r = n.toString(16);
return r.length !== 2 ? `0${r}` : r;
}
function _toTwoDigitHex(n: number): string {
const r = n.toString(16);
return r.length !== 2 ? `0${r}` : r;
}
/**
* Formats the color as #RRGGBB
*/
export function formatHex(color: Color): string {
return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(color.rgba.b)}`;
}
/**
* Formats the color as #RRGGBB
*/
export function formatHex(color: Color): string {
return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(color.rgba.b)}`;
}
/**
* Formats the color as #RRGGBBAA
* If 'compact' is set, colors without transparancy will be printed as #RRGGBB
*/
export function formatHexA(color: Color, compact = false): string {
if (compact && color.rgba.a === 1) {
return Color.Format.CSS.formatHex(color);
}
return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(
color.rgba.b,
)}${_toTwoDigitHex(Math.round(color.rgba.a * 255))}`;
}
/**
* Formats the color as #RRGGBBAA
* If 'compact' is set, colors without transparancy will be printed as #RRGGBB
*/
export function formatHexA(color: Color, compact = false): string {
if (compact && color.rgba.a === 1) {
return formatHex(color);
}
/**
* The default format will use HEX if opaque and RGBA otherwise.
*/
export function format(color: Color): string {
if (color.isOpaque()) {
return Color.Format.CSS.formatHex(color);
}
return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(
color.rgba.b,
)}${_toTwoDigitHex(Math.round(color.rgba.a * 255))}`;
}
return Color.Format.CSS.formatRGBA(color);
}
/**
* The default format will use HEX if opaque and RGBA otherwise.
*/
export function format(color: Color): string {
if (color.isOpaque()) {
return formatHex(color);
}
export function parseString(value: string): Color | null {
const length = value.length;
// Invalid color
if (length === 0) {
return null;
}
// Begin with a #
if (value.charCodeAt(0) === CharCode.Hash) {
return Color.Format.CSS.parseHex(value);
}
const result = cssColorRegex.exec(value);
if (result == null) {
return null;
}
const mode = result[3];
let colors: number[];
switch (mode) {
case 'rgb':
case 'hsl':
colors = [parseInt(result[4], 10), parseInt(result[5], 10), parseInt(result[6], 10), 1];
break;
case 'rgba':
case 'hsla':
colors = [
parseInt(result[4], 10),
parseInt(result[5], 10),
parseInt(result[6], 10),
parseFloat(result[7]),
];
break;
default:
return null;
}
switch (mode) {
case 'rgb':
case 'rgba':
return new Color(new RGBA(colors[0], colors[1], colors[2], colors[3]));
case 'hsl':
case 'hsla':
return new Color(new HSLA(colors[0], colors[1], colors[2], colors[3]));
}
return Color.red;
}
return formatRGBA(color);
}
/**
* Converts an Hex color value to a Color.
* returns r, g, and b are contained in the set [0, 255]
* @param hex string (#RGB, #RGBA, #RRGGBB or #RRGGBBAA).
*/
export function parseHex(hex: string): Color | null {
const length = hex.length;
if (length === 0) {
// Invalid color
return null;
}
if (hex.charCodeAt(0) !== CharCode.Hash) {
// Does not begin with a #
return null;
}
if (length === 7) {
// #RRGGBB format
const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
return new Color(new RGBA(r, g, b, 1));
}
if (length === 9) {
// #RRGGBBAA format
const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
const a = 16 * _parseHexDigit(hex.charCodeAt(7)) + _parseHexDigit(hex.charCodeAt(8));
return new Color(new RGBA(r, g, b, a / 255));
}
if (length === 4) {
// #RGB format
const r = _parseHexDigit(hex.charCodeAt(1));
const g = _parseHexDigit(hex.charCodeAt(2));
const b = _parseHexDigit(hex.charCodeAt(3));
return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b));
}
if (length === 5) {
// #RGBA format
const r = _parseHexDigit(hex.charCodeAt(1));
const g = _parseHexDigit(hex.charCodeAt(2));
const b = _parseHexDigit(hex.charCodeAt(3));
const a = _parseHexDigit(hex.charCodeAt(4));
return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b, (16 * a + a) / 255));
}
// Invalid color
return null;
}
export function parseString(value: string): Color | null {
const length = value.length;
function _parseHexDigit(charCode: CharCode): number {
switch (charCode) {
case CharCode.Digit0:
return 0;
case CharCode.Digit1:
return 1;
case CharCode.Digit2:
return 2;
case CharCode.Digit3:
return 3;
case CharCode.Digit4:
return 4;
case CharCode.Digit5:
return 5;
case CharCode.Digit6:
return 6;
case CharCode.Digit7:
return 7;
case CharCode.Digit8:
return 8;
case CharCode.Digit9:
return 9;
case CharCode.a:
return 10;
case CharCode.A:
return 10;
case CharCode.b:
return 11;
case CharCode.B:
return 11;
case CharCode.c:
return 12;
case CharCode.C:
return 12;
case CharCode.d:
return 13;
case CharCode.D:
return 13;
case CharCode.e:
return 14;
case CharCode.E:
return 14;
case CharCode.f:
return 15;
case CharCode.F:
return 15;
}
return 0;
}
}
// Invalid color
if (length === 0) {
return null;
}
// Begin with a #
if (value.charCodeAt(0) === CharCode.Hash) {
return parseHex(value);
}
const result = cssColorRegex.exec(value);
if (result == null) {
return null;
}
const mode = result[3];
let colors: number[];
switch (mode) {
case 'rgb':
case 'hsl':
colors = [parseInt(result[4], 10), parseInt(result[5], 10), parseInt(result[6], 10), 1];
break;
case 'rgba':
case 'hsla':
colors = [parseInt(result[4], 10), parseInt(result[5], 10), parseInt(result[6], 10), parseFloat(result[7])];
break;
default:
return null;
}
switch (mode) {
case 'rgb':
case 'rgba':
return new Color(new RGBA(colors[0], colors[1], colors[2], colors[3]));
case 'hsl':
case 'hsla':
return new Color(new HSLA(colors[0], colors[1], colors[2], colors[3]));
}
return Color.red;
}
/**
* Converts an Hex color value to a Color.
* returns r, g, and b are contained in the set [0, 255]
* @param hex string (#RGB, #RGBA, #RRGGBB or #RRGGBBAA).
*/
export function parseHex(hex: string): Color | null {
const length = hex.length;
if (length === 0) {
// Invalid color
return null;
}
if (hex.charCodeAt(0) !== CharCode.Hash) {
// Does not begin with a #
return null;
}
if (length === 7) {
// #RRGGBB format
const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
return new Color(new RGBA(r, g, b, 1));
}
if (length === 9) {
// #RRGGBBAA format
const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
const a = 16 * _parseHexDigit(hex.charCodeAt(7)) + _parseHexDigit(hex.charCodeAt(8));
return new Color(new RGBA(r, g, b, a / 255));
}
if (length === 4) {
// #RGB format
const r = _parseHexDigit(hex.charCodeAt(1));
const g = _parseHexDigit(hex.charCodeAt(2));
const b = _parseHexDigit(hex.charCodeAt(3));
return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b));
}
if (length === 5) {
// #RGBA format
const r = _parseHexDigit(hex.charCodeAt(1));
const g = _parseHexDigit(hex.charCodeAt(2));
const b = _parseHexDigit(hex.charCodeAt(3));
const a = _parseHexDigit(hex.charCodeAt(4));
return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b, (16 * a + a) / 255));
}
// Invalid color
return null;
}
function _parseHexDigit(charCode: CharCode): number {
switch (charCode) {
case CharCode.Digit0:
return 0;
case CharCode.Digit1:
return 1;
case CharCode.Digit2:
return 2;
case CharCode.Digit3:
return 3;
case CharCode.Digit4:
return 4;
case CharCode.Digit5:
return 5;
case CharCode.Digit6:
return 6;
case CharCode.Digit7:
return 7;
case CharCode.Digit8:
return 8;
case CharCode.Digit9:
return 9;
case CharCode.a:
return 10;
case CharCode.A:
return 10;
case CharCode.b:
return 11;
case CharCode.B:
return 11;
case CharCode.c:
return 12;
case CharCode.C:
return 12;
case CharCode.d:
return 13;
case CharCode.D:
return 13;
case CharCode.e:
return 14;
case CharCode.E:
return 14;
case CharCode.f:
return 15;
case CharCode.F:
return 15;
}
return 0;
}

Loading…
Cancel
Save