devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
203 lines (202 loc) • 7.66 kB
JavaScript
import { Errors } from '@devexpress/utils/lib/errors';
import { ColorUtils } from '@devexpress/utils/lib/utils/color';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { MathUtils } from '@devexpress/utils/lib/utils/math';
import { Log } from '../../rich-utils/debug/logger/base-logger/log';
import { DrawingValueConstants } from '../drawing/drawing-value-constants';
import { DXColor } from './dx-color';
export class ColorHSL {
constructor(hue, saturation, luminance) {
if (Log.isEnabled && !(hue <= 1 && hue >= 0 && saturation <= 1 && saturation >= 0 && luminance <= 1 && luminance >= 0))
throw new Error(Errors.InternalException);
this._hue = hue;
this._saturation = saturation;
this._luminance = luminance;
}
calculateHash() {
return MathUtils.somePrimes[0] * this._hue ^
MathUtils.somePrimes[0] * this._luminance ^
MathUtils.somePrimes[0] * this._saturation;
}
static makeFromHSL(hue, saturation, luminance) {
return new ColorHSL(hue / ColorHSL.MaxAngle, saturation / ColorHSL.MaxThousandthOfPercentage, luminance / ColorHSL.MaxThousandthOfPercentage);
}
static rgbToHsl(r, g, b) {
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0;
}
else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, l];
}
static fromColorRGB(color) {
const r = ColorUtils.getRed(color) / 255;
const g = ColorUtils.getGreen(color) / 255;
const b = ColorUtils.getBlue(color) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h;
let s;
const l = (max + min) / 2;
if (max == min) {
s = 0;
h = 4.0 / 6.0;
}
else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return new ColorHSL(h, s, l);
}
static calculateColorRGB(color, tint) {
if (color == DXColor.empty || tint == 0)
return color;
return ColorHSL.fromColorRGB(color).applyTint(tint).toRgb();
}
toRgb() {
const value1 = (this._luminance < 0.5) ?
this._luminance * (1 + this._saturation) :
this._luminance + this._saturation - this._luminance * this._saturation;
const value2 = 2 * this._luminance - value1;
const rgb = ListUtils.map([this._hue + 1.0 / 3.0, this._hue, this._hue - 1.0 / 3.0], (value) => {
if (value < 0)
value += 1;
if (value > 1)
value -= 1;
if (6 * value < 1)
value = value2 + ((value1 - value2) * 6 * value);
else if (6 * value >= 1 && 6 * value < 3)
value = value1;
else if (6 * value >= 3 && 6 * value < 4)
value = value2 + ((value1 - value2) * (4 - 6 * value));
else
value = value2;
return this.toIntValue(value);
});
return DXColor.fromRgb(rgb[0], rgb[1], rgb[2]);
}
get hue() { return this.getIntValue(this._hue, ColorHSL.MaxAngle); }
;
set hue(value) { this._hue = this.getFloatValue(this.getValidValue(value), ColorHSL.MaxAngle); }
get saturation() { return this.getIntValue(this._saturation, ColorHSL.MaxThousandthOfPercentage); }
;
set saturation(value) { this._saturation = this.getFloatValue(this.getValidValue(value), ColorHSL.MaxThousandthOfPercentage); }
get luminance() { return this.getIntValue(this._luminance, ColorHSL.MaxThousandthOfPercentage); }
;
set luminance(value) { this._luminance = this.getFloatValue(this.getValidValue(value), ColorHSL.MaxThousandthOfPercentage); }
get floatHue() { return this._hue; }
;
set floatHue(value) { this._hue = this.getValidValue(value); }
get floatSaturation() { return this._saturation; }
;
set floatSaturation(value) { this._saturation = this.getValidValue(value); }
get floatLuminance() { return this._luminance; }
;
set floatLuminance(value) { this._luminance = this.getValidValue(value); }
getComplementColor() {
this._hue += this._hue > 0.5 ? -0.5 : 0.5;
return this;
}
applyHue(value) {
this.floatHue = value / ColorHSL.MaxAngle;
return this;
}
applyHueMod(value) {
this._hue = this._hue * value / ColorHSL.MaxThousandthOfPercentage;
this.fixHue();
return this;
}
applyHueOffset(value) {
this._hue += value / ColorHSL.MaxAngle;
this.fixHue();
return this;
}
applySaturation(value) {
this.floatSaturation = value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
applySaturationMod(value) {
this._saturation = this._saturation * value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
applySaturationOffset(value) {
this._saturation += value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
applyLuminance(value) {
this.floatLuminance = value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
applyLuminanceMod(value) {
this._luminance = this._luminance * value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
applyLuminanceOffset(value) {
this._luminance += value / ColorHSL.MaxThousandthOfPercentage;
return this;
}
fixHue() {
if (this._hue > 1)
this._hue -= Math.floor(this._hue);
}
toIntValue(value) {
return this.fixIntValue(Math.round(255 * value));
}
fixIntValue(value) {
return MathUtils.restrictValue(value, 0, 255);
}
getIntValue(value, maxValue) {
return Math.round(value * maxValue);
}
getFloatValue(value, maxValue) {
return value / maxValue;
}
getValidValue(value) {
return MathUtils.restrictValue(value, 0, 1);
}
applyTint(tint) {
if (tint < 0)
this._luminance *= (1 + tint);
else if (tint > 0)
this._luminance = this._luminance * (1 - tint) + tint;
return this;
}
equals(obj) {
return obj &&
this._hue == obj._hue &&
this._saturation == obj._saturation &&
this._luminance == obj._luminance;
}
}
ColorHSL.MaxAngle = DrawingValueConstants.MaxPositiveFixedAngle;
ColorHSL.MaxThousandthOfPercentage = DrawingValueConstants.ThousandthOfPercentage;
ColorHSL.defaultValue = new ColorHSL(0, 0, 0);