mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
feat(color): added utilities and improved color parsing performance (#9110)
This commit is contained in:

committed by
Nathan Walker

parent
65f9598a0d
commit
c4db847ded
@ -1,7 +1,6 @@
|
||||
import * as definition from '.';
|
||||
import * as definition from '.';
|
||||
import * as types from '../utils/types';
|
||||
import * as knownColors from './known-colors';
|
||||
import { convertHSLToRGBColor } from '../css/parser';
|
||||
|
||||
const SHARP = '#';
|
||||
const HEX_REGEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i;
|
||||
@ -12,26 +11,28 @@ export class Color implements definition.Color {
|
||||
|
||||
constructor(color: number);
|
||||
constructor(color: string);
|
||||
constructor(a: number, r: number, g: number, b: number);
|
||||
constructor(a: number, r: number, g: number, b: number, type?: 'rbg' | 'hsl' | 'hsv');
|
||||
constructor(...args) {
|
||||
if (args.length === 1) {
|
||||
const arg = args[0];
|
||||
if (types.isString(arg)) {
|
||||
if (isRgbOrRgba(arg)) {
|
||||
this._argb = argbFromRgbOrRgba(arg);
|
||||
} else if (isHslOrHsla(arg)) {
|
||||
this._argb = argbFromHslOrHsla(arg);
|
||||
} else if (knownColors.isKnownName(arg)) {
|
||||
const lowered = arg.toLowerCase();
|
||||
if (isRgbOrRgba(lowered)) {
|
||||
this._argb = argbFromRgbOrRgba(lowered);
|
||||
} else if (isHslOrHsla(lowered)) {
|
||||
this._argb = argbFromHslOrHsla(lowered);
|
||||
} else if (isHsvOrHsva(lowered)) {
|
||||
this._argb = argbFromHsvOrHsva(lowered);
|
||||
} else if (knownColors.isKnownName(lowered)) {
|
||||
// The parameter is a known color name
|
||||
const argb = knownColors.getKnownColor(arg);
|
||||
const argb = knownColors.getKnownColor(lowered);
|
||||
this._name = arg;
|
||||
this._argb = argb;
|
||||
} else if (arg[0].charAt(0) === SHARP && (arg.length === 4 || arg.length === 7 || arg.length === 9)) {
|
||||
// we dont use the regexp as it is quite slow. Instead we expect it to be a valid hex format
|
||||
// strange that it would not be. And if it is not a thrown error seems best
|
||||
// The parameter is a "#RRGGBBAA" formatted string
|
||||
const hex = this._normalizeHex(arg);
|
||||
this._argb = this._argbFromString(hex);
|
||||
this._argb = this._argbFromString(arg);
|
||||
} else {
|
||||
throw new Error('Invalid color: ' + arg);
|
||||
}
|
||||
@ -47,8 +48,23 @@ export class Color implements definition.Color {
|
||||
} else {
|
||||
throw new Error('Expected 1 or 4 constructor parameters.');
|
||||
}
|
||||
} else if (args.length === 4) {
|
||||
this._argb = (args[0] & 0xff) * 0x01000000 + (args[1] & 0xff) * 0x00010000 + (args[2] & 0xff) * 0x00000100 + (args[3] & 0xff) * 0x00000001;
|
||||
} else if (args.length >= 4) {
|
||||
const a = args[0];
|
||||
switch (args[4]) {
|
||||
case 'hsl': {
|
||||
const { r, g, b } = hslToRgb(args[1], args[2], args[3]);
|
||||
this._argb = (a & 0xff) * 0x01000000 + (r & 0xff) * 0x00010000 + (g & 0xff) * 0x00000100 + (b & 0xff) * 0x00000001;
|
||||
break;
|
||||
}
|
||||
case 'hsv': {
|
||||
const { r, g, b } = hsvToRgb(args[1], args[2], args[3]);
|
||||
this._argb = (a & 0xff) * 0x01000000 + (r & 0xff) * 0x00010000 + (g & 0xff) * 0x00000100 + (b & 0xff) * 0x00000001;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this._argb = (a & 0xff) * 0x01000000 + (args[1] & 0xff) * 0x00010000 + (args[2] & 0xff) * 0x00000100 + (args[3] & 0xff) * 0x00000001;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
throw new Error('Expected 1 or 4 constructor parameters.');
|
||||
}
|
||||
@ -72,11 +88,11 @@ export class Color implements definition.Color {
|
||||
}
|
||||
|
||||
get hex(): string {
|
||||
if (this.a === 0xff) {
|
||||
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
||||
} else {
|
||||
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b) + this._componentToHex(this.a)).toUpperCase();
|
||||
let result = SHARP + ('000000' + (this._argb & 0xffffff).toString(16)).toUpperCase().slice(-6);
|
||||
if (this.a !== 0xff) {
|
||||
return (result += ('00' + this.a.toString(16).toUpperCase()).slice(-2));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
@ -92,13 +108,13 @@ export class Color implements definition.Color {
|
||||
}
|
||||
|
||||
public _argbFromString(hex: string): number {
|
||||
if (hex.charAt(0) === '#') {
|
||||
hex = hex.substr(1);
|
||||
}
|
||||
|
||||
if (hex.length === 3) {
|
||||
// always called as SHARP as first char
|
||||
hex = hex.substr(1);
|
||||
const length = hex.length;
|
||||
// first we normalize
|
||||
if (length === 3) {
|
||||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||
} else if (hex.length === 4) {
|
||||
} else if (length === 4) {
|
||||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
|
||||
}
|
||||
|
||||
@ -142,35 +158,19 @@ export class Color implements definition.Color {
|
||||
if (!types.isString(value)) {
|
||||
return false;
|
||||
}
|
||||
const lowered = value.toLowerCase();
|
||||
|
||||
if (knownColors.isKnownName(value)) {
|
||||
if (knownColors.isKnownName(lowered)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return HEX_REGEX.test(value) || isRgbOrRgba(value) || isHslOrHsla(value);
|
||||
return HEX_REGEX.test(value) || isRgbOrRgba(lowered) || isHslOrHsla(lowered);
|
||||
}
|
||||
public static fromHSL(a, h, s, l) {
|
||||
const rgb = hslToRgb(h, s, l);
|
||||
return new Color(a, rgb.r, rgb.g, rgb.b);
|
||||
return new Color(a, h, s, l, 'hsl');
|
||||
}
|
||||
|
||||
private _componentToHex(component: number): string {
|
||||
let hex = component.toString(16);
|
||||
if (hex.length === 1) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
private _normalizeHex(hexStr: string): string {
|
||||
// we expect this to already has a # as first char as it is supposed to be tested before
|
||||
if (hexStr.length === 4) {
|
||||
// Duplicate each char after the #, so "#123" becomes "#112233"
|
||||
hexStr = hexStr.charAt(0) + hexStr.charAt(1) + hexStr.charAt(1) + hexStr.charAt(2) + hexStr.charAt(2) + hexStr.charAt(3) + hexStr.charAt(3);
|
||||
}
|
||||
|
||||
return hexStr;
|
||||
public static fromHSV(a, h, s, l) {
|
||||
return new Color(a, h, s, l, 'hsv');
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
@ -247,7 +247,7 @@ export class Color implements definition.Color {
|
||||
*
|
||||
*/
|
||||
public toHsl() {
|
||||
const hsl = rgbToHsl(this.r, this.g, this.b);
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this.a };
|
||||
}
|
||||
|
||||
@ -256,7 +256,7 @@ export class Color implements definition.Color {
|
||||
*
|
||||
*/
|
||||
public toHslString() {
|
||||
const hsl = rgbToHsl(this.r, this.g, this.b);
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
const h = Math.round(hsl.h * 360),
|
||||
s = Math.round(hsl.s * 100),
|
||||
l = Math.round(hsl.l * 100);
|
||||
@ -269,7 +269,7 @@ export class Color implements definition.Color {
|
||||
*
|
||||
*/
|
||||
public toHsv() {
|
||||
const hsv = rgbToHsv(this.r, this.g, this.b);
|
||||
const hsv = rgbToHsv(this.r / 255, this.g / 255, this.b / 255);
|
||||
return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this.a };
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ export class Color implements definition.Color {
|
||||
*
|
||||
*/
|
||||
public toHsvString() {
|
||||
const hsv = rgbToHsv(this.r, this.g, this.b);
|
||||
const hsv = rgbToHsv(this.r / 255, this.g / 255, this.b / 255);
|
||||
const h = Math.round(hsv.h * 360),
|
||||
s = Math.round(hsv.s * 100),
|
||||
v = Math.round(hsv.v * 100);
|
||||
@ -302,10 +302,10 @@ export class Color implements definition.Color {
|
||||
*/
|
||||
public desaturate(amount: number) {
|
||||
amount = amount === 0 ? 0 : amount || 10;
|
||||
const hsl = this.toHsl();
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
hsl.s -= amount / 100;
|
||||
hsl.s = Math.min(1, Math.max(0, hsl.s));
|
||||
return Color.fromHSL(this.a, hsl.h, hsl.s, hsl.l);
|
||||
return Color.fromHSL(this.a, hsl.h * 360, hsl.s * 100, hsl.l * 100);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,10 +315,10 @@ export class Color implements definition.Color {
|
||||
*/
|
||||
public saturate(amount: number) {
|
||||
amount = amount === 0 ? 0 : amount || 10;
|
||||
const hsl = this.toHsl();
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
hsl.s += amount / 100;
|
||||
hsl.s = Math.min(1, Math.max(0, hsl.s));
|
||||
return Color.fromHSL(this.a, hsl.h, hsl.s, hsl.l);
|
||||
return Color.fromHSL(this.a, hsl.h * 360, hsl.s * 100, hsl.l * 100);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,10 +336,10 @@ export class Color implements definition.Color {
|
||||
*/
|
||||
public lighten(amount: number) {
|
||||
amount = amount === 0 ? 0 : amount || 10;
|
||||
const hsl = this.toHsl();
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
hsl.l += amount / 100;
|
||||
hsl.l = Math.min(1, Math.max(0, hsl.l));
|
||||
return Color.fromHSL(this.a, hsl.h, hsl.s, hsl.l);
|
||||
return Color.fromHSL(this.a, hsl.h * 360, hsl.s * 100, hsl.l * 100);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -362,16 +362,14 @@ export class Color implements definition.Color {
|
||||
*/
|
||||
public darken(amount: number) {
|
||||
amount = amount === 0 ? 0 : amount || 10;
|
||||
const hsl = this.toHsl();
|
||||
hsl.l -= amount / 100;
|
||||
hsl.l = Math.min(1, Math.max(0, hsl.l));
|
||||
return Color.fromHSL(this.a, hsl.h, hsl.s, hsl.l);
|
||||
const hsl = rgbToHsl(this.r / 255, this.g / 255, this.b / 255);
|
||||
return Color.fromHSL(this.a, hsl.h * 360, hsl.s * 100, Math.min(100, Math.max(0, hsl.l - amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Spin the hue a given amount, from -360 to 360. Calling with 0, 360, or -360 will do nothing (since it sets the hue back to what it was before).
|
||||
*
|
||||
* @param amount (between 0 and 100)
|
||||
* @param amount (between -360 and 360)
|
||||
*/
|
||||
public spin(amount: number) {
|
||||
const hsl = this.toHsl();
|
||||
@ -389,25 +387,37 @@ export class Color implements definition.Color {
|
||||
hsl.h = (hsl.h + 180) % 360;
|
||||
return Color.fromHSL(this.a, hsl.h, hsl.s, hsl.l);
|
||||
}
|
||||
|
||||
static mix(color1: Color, color2: Color, amount = 50) {
|
||||
const p = amount / 100;
|
||||
|
||||
const rgba = {
|
||||
r: (color2.r - color1.r) * p + color1.r,
|
||||
g: (color2.g - color1.g) * p + color1.g,
|
||||
b: (color2.b - color1.b) * p + color1.b,
|
||||
a: (color2.a - color1.a) * p + color1.a,
|
||||
};
|
||||
|
||||
return new Color(rgba.a, rgba.r, rgba.g, rgba.b);
|
||||
}
|
||||
}
|
||||
|
||||
function isRgbOrRgba(value: string): boolean {
|
||||
const toLower = value.toLowerCase();
|
||||
|
||||
return (toLower.indexOf('rgb(') === 0 || toLower.indexOf('rgba(') === 0) && toLower.indexOf(')') === toLower.length - 1;
|
||||
return (value.startsWith('rgb(') || value.startsWith('rgba(')) && value.endsWith(')');
|
||||
}
|
||||
|
||||
function isHslOrHsla(value: string): boolean {
|
||||
const toLower = value.toLowerCase();
|
||||
|
||||
return (toLower.indexOf('hsl(') === 0 || toLower.indexOf('hsla(') === 0) && toLower.indexOf(')') === toLower.length - 1;
|
||||
return (value.startsWith('hsl') || value.startsWith('hsla(')) && value.endsWith(')');
|
||||
}
|
||||
function isHsvOrHsva(value: string): boolean {
|
||||
return (value.startsWith('hsv') || value.startsWith('hsva(')) && value.endsWith(')');
|
||||
}
|
||||
|
||||
function parseColorWithAlpha(value: string): any {
|
||||
const toLower = value.toLowerCase();
|
||||
const parts = toLower
|
||||
.replace(/(rgb|hsl)a?\(/, '')
|
||||
const parts = value
|
||||
.replace(/(rgb|hsl|hsv)a?\(/, '')
|
||||
.replace(')', '')
|
||||
.replace(/%/g, '')
|
||||
.trim()
|
||||
.split(',');
|
||||
|
||||
@ -444,14 +454,22 @@ function argbFromRgbOrRgba(value: string): number {
|
||||
function argbFromHslOrHsla(value: string): number {
|
||||
const { f: h, s: s, t: l, a } = parseColorWithAlpha(value);
|
||||
|
||||
const { r, g, b } = convertHSLToRGBColor(h, s, l);
|
||||
const { r, g, b } = hslToRgb(h, s, l);
|
||||
|
||||
return (a & 0xff) * 0x01000000 + (r & 0xff) * 0x00010000 + (g & 0xff) * 0x00000100 + (b & 0xff);
|
||||
}
|
||||
|
||||
function argbFromHsvOrHsva(value: string): number {
|
||||
const { f: h, s: s, t: v, a } = parseColorWithAlpha(value);
|
||||
|
||||
const { r, g, b } = hsvToRgb(h, s, v);
|
||||
|
||||
return (a & 0xff) * 0x01000000 + (r & 0xff) * 0x00010000 + (g & 0xff) * 0x00000100 + (b & 0xff);
|
||||
}
|
||||
|
||||
// `rgbToHsl`
|
||||
// Converts an RGB color value to HSL.
|
||||
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
|
||||
// *Assumes:* r, g, and b are contained in [0, 1]
|
||||
// *Returns:* { h, s, l } in [0,1]
|
||||
function rgbToHsl(r, g, b) {
|
||||
const max = Math.max(r, g, b),
|
||||
@ -493,9 +511,12 @@ function hue2rgb(p, q, t) {
|
||||
|
||||
// `hslToRgb`
|
||||
// Converts an HSL color value to RGB.
|
||||
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
|
||||
// *Assumes:* h is contained in [0, 360] and s and l are contained [0, 100]
|
||||
// *Returns:* { r, g, b } in the set [0, 255]
|
||||
function hslToRgb(h, s, l) {
|
||||
function hslToRgb(h1, s1, l1) {
|
||||
const h = (h1 % 360) / 360;
|
||||
const s = s1 / 100;
|
||||
const l = l1 / 100;
|
||||
let r, g, b;
|
||||
if (s === 0) {
|
||||
r = g = b = l; // achromatic
|
||||
@ -512,7 +533,7 @@ function hslToRgb(h, s, l) {
|
||||
|
||||
// `rgbToHsv`
|
||||
// Converts an RGB color value to HSV
|
||||
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
|
||||
// *Assumes:* r, g, and b are contained in the set [0, 1]
|
||||
// *Returns:* { h, s, v } in [0,1]
|
||||
function rgbToHsv(r, g, b) {
|
||||
const max = Math.max(r, g, b),
|
||||
@ -541,3 +562,25 @@ function rgbToHsv(r, g, b) {
|
||||
}
|
||||
return { h: h, s: s, v: v };
|
||||
}
|
||||
|
||||
// `hsvToRgb`
|
||||
// Converts an HSV color value to RGB.
|
||||
// *Assumes:* h is contained in [0, 360] and s and v are contained [0, 100]
|
||||
// *Returns:* { r, g, b } in the set [0, 255]
|
||||
function hsvToRgb(h1, s1, v1) {
|
||||
const h = ((h1 % 360) / 360) * 6;
|
||||
const s = s1 / 100;
|
||||
const v = v1 / 100;
|
||||
|
||||
var i = Math.floor(h),
|
||||
f = h - i,
|
||||
p = v * (1 - s),
|
||||
q = v * (1 - f * s),
|
||||
t = v * (1 - (1 - f) * s),
|
||||
mod = i % 6,
|
||||
r = [v, q, p, p, t, v][mod],
|
||||
g = [t, v, v, q, p, p][mod],
|
||||
b = [p, p, t, v, v, q][mod];
|
||||
|
||||
return { r: r * 255, g: g * 255, b: b * 255 };
|
||||
}
|
||||
|
17
packages/core/color/index.d.ts
vendored
17
packages/core/color/index.d.ts
vendored
@ -1,11 +1,11 @@
|
||||
/**
|
||||
/**
|
||||
* Represents a color object. Stores all color components (alpha (opacity), red, green, blue) in a [0..255] range.
|
||||
*/
|
||||
export class Color {
|
||||
constructor(knownColor: string);
|
||||
constructor(hex: string);
|
||||
constructor(argb: number);
|
||||
constructor(alpha: number, red: number, green: number, blue: number);
|
||||
constructor(alpha: number, red: number, green: number, blue: number, type?: 'rgb' | 'hsl' | 'hsv');
|
||||
|
||||
/**
|
||||
* Gets the Alpha component (in the [0, 255] range) of this color. This is a read-only property.
|
||||
@ -190,4 +190,17 @@ export class Color {
|
||||
*
|
||||
*/
|
||||
public complement(): Color;
|
||||
|
||||
/**
|
||||
* returns the color complement
|
||||
*
|
||||
*/
|
||||
public static mix(color1: Color, color2: Color, amount: number): Color;
|
||||
|
||||
/**
|
||||
* returns a new Color from HSL
|
||||
*
|
||||
*/
|
||||
public static fromHSL(a, h, s, l): Color;
|
||||
public static fromHSV(a, h, s, l): Color;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Color } from '../color';
|
||||
import { getKnownColor } from '../color/known-colors';
|
||||
|
||||
export type Parsed<V> = { start: number; end: number; value: V };
|
||||
|
||||
// Values
|
||||
export type ARGB = number;
|
||||
export type URL = string;
|
||||
export type Angle = number;
|
||||
export interface Unit<T> {
|
||||
@ -15,7 +15,7 @@ export type Percentage = Unit<'%'>;
|
||||
export type LengthPercentage = Length | Percentage;
|
||||
export type Keyword = string;
|
||||
export interface ColorStop {
|
||||
argb: ARGB;
|
||||
color: Color;
|
||||
offset?: LengthPercentage;
|
||||
}
|
||||
export interface LinearGradient {
|
||||
@ -67,59 +67,31 @@ export function parseURL(text: string, start = 0): Parsed<URL> {
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
const hexColorRegEx = /\s*#((?:[0-9A-F]{8})|(?:[0-9A-F]{6})|(?:[0-9A-F]{3}))\s*/giy;
|
||||
export function parseHexColor(text: string, start = 0): Parsed<ARGB> {
|
||||
const hexColorRegEx = /\s*#((?:[0-9A-F]{8})|(?:[0-9A-F]{6})|(?:[0-9A-F]{4})|(?:[0-9A-F]{3}))\s*/giy;
|
||||
export function parseHexColor(text: string, start = 0): Parsed<Color> {
|
||||
hexColorRegEx.lastIndex = start;
|
||||
const result = hexColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = hexColorRegEx.lastIndex;
|
||||
const hex = result[1];
|
||||
let argb;
|
||||
if (hex.length === 8) {
|
||||
argb = parseInt('0x' + hex);
|
||||
} else if (hex.length === 6) {
|
||||
argb = parseInt('0xFF' + hex);
|
||||
} else if (hex.length === 3) {
|
||||
argb = parseInt('0xFF' + hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]);
|
||||
}
|
||||
|
||||
return { start, end, value: argb };
|
||||
return { start, end, value: new Color('#'+ result[1]) };
|
||||
}
|
||||
|
||||
function rgbaToArgbNumber(r: number, g: number, b: number, a = 1): number | undefined {
|
||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) {
|
||||
return Math.round(a * 0xff) * 0x01000000 + r * 0x010000 + g * 0x000100 + b;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const rgbColorRegEx = /\s*(rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\))/gy;
|
||||
export function parseRGBColor(text: string, start = 0): Parsed<ARGB> {
|
||||
rgbColorRegEx.lastIndex = start;
|
||||
const result = rgbColorRegEx.exec(text);
|
||||
const cssColorRegEx = /\s*((?:rgb|rgba|hsl|hsla|hsv|hsva)\([^\(\)]\))/gy;
|
||||
export function parseCssColor(text: string, start = 0): Parsed<Color> {
|
||||
cssColorRegEx.lastIndex = start;
|
||||
const result = cssColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = rgbColorRegEx.lastIndex;
|
||||
const value = result[1] && rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
const rgbaColorRegEx = /\s*(rgba\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*,\s*([01]?\.?\d*)\s*\))/gy;
|
||||
export function parseRGBAColor(text: string, start = 0): Parsed<ARGB> {
|
||||
rgbaColorRegEx.lastIndex = start;
|
||||
const result = rgbaColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
const end = cssColorRegEx.lastIndex;
|
||||
try {
|
||||
return { start, end, value: new Color(text) };
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const end = rgbaColorRegEx.lastIndex;
|
||||
const value = rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4]), parseFloat(result[5]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
export function convertHSLToRGBColor(hue: number, saturation: number, lightness: number): { r: number; g: number; b: number } {
|
||||
@ -160,49 +132,19 @@ export function convertHSLToRGBColor(hue: number, saturation: number, lightness:
|
||||
};
|
||||
}
|
||||
|
||||
function hslaToArgbNumber(h: number, s: number, l: number, a = 1): number | undefined {
|
||||
const { r, g, b } = convertHSLToRGBColor(h, s, l);
|
||||
return rgbaToArgbNumber(r, g, b, a);
|
||||
}
|
||||
|
||||
const hslColorRegEx = /\s*(hsl\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*\))/gy;
|
||||
export function parseHSLColor(text: string, start = 0): Parsed<ARGB> {
|
||||
hslColorRegEx.lastIndex = start;
|
||||
const result = hslColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = hslColorRegEx.lastIndex;
|
||||
const value = result[1] && hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
const hslaColorRegEx = /\s*(hsla\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*,\s*([01]?\.?\d*)\s*\))/gy;
|
||||
export function parseHSLAColor(text: string, start = 0): Parsed<ARGB> {
|
||||
hslaColorRegEx.lastIndex = start;
|
||||
const result = hslaColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = hslaColorRegEx.lastIndex;
|
||||
const value = hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]), parseFloat(result[5]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
export function parseColorKeyword(value, start: number, keyword = parseKeyword(value, start)): Parsed<ARGB> {
|
||||
export function parseColorKeyword(value, start: number, keyword = parseKeyword(value, start)): Parsed<Color> {
|
||||
const parseColor = keyword && getKnownColor(keyword.value);
|
||||
if (parseColor != null) {
|
||||
const end = keyword.end;
|
||||
const value = parseColor;
|
||||
return { start, end, value };
|
||||
return { start, end, value: new Color(parseColor) };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function parseColor(value: string, start = 0, keyword = parseKeyword(value, start)): Parsed<ARGB> {
|
||||
return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseRGBColor(value, start) || parseRGBAColor(value, start) || parseHSLColor(value, start) || parseHSLAColor(value, start);
|
||||
export function parseColor(value: string, start = 0, keyword = parseKeyword(value, start)): Parsed<Color> {
|
||||
return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseCssColor(value, start);
|
||||
}
|
||||
|
||||
const keywordRegEx = /\s*([a-z][\w\-]*)\s*/giy;
|
||||
@ -558,11 +500,11 @@ export function parseColorStop(text: string, start = 0): Parsed<ColorStop> {
|
||||
return {
|
||||
start,
|
||||
end,
|
||||
value: { argb: color.value, offset: offset.value },
|
||||
value: { color: color.value, offset: offset.value },
|
||||
};
|
||||
}
|
||||
|
||||
return { start, end, value: { argb: color.value } };
|
||||
return { start, end, value: { color: color.value } };
|
||||
}
|
||||
|
||||
const linearGradientStartRegEx = /\s*linear-gradient\s*/gy;
|
||||
|
@ -22,7 +22,7 @@ export class LinearGradient {
|
||||
}
|
||||
|
||||
return {
|
||||
color: new Color(color.argb),
|
||||
color: color.color,
|
||||
offset: offsetUnit,
|
||||
};
|
||||
});
|
||||
|
Reference in New Issue
Block a user