mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-21 13:30:54 +00:00
Refactored colors. Fixed scrolling on mobile. Added image preview on hover.
This commit is contained in:
parent
2bc2b7003b
commit
02b0a95bd0
22 changed files with 2121 additions and 425 deletions
634
src/colors.js
Normal file
634
src/colors.js
Normal file
|
@ -0,0 +1,634 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
|
||||
hue2rgb = function(p, q, t) {
|
||||
if ( t < 0 ) t += 1;
|
||||
if ( t > 1 ) t -= 1;
|
||||
if ( t < 1/6 )
|
||||
return p + (q-p) * 6 * t;
|
||||
if ( t < 1/2 )
|
||||
return q;
|
||||
if ( t < 2/3 )
|
||||
return p + (q-p) * (2/3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Settings
|
||||
// ---------------------
|
||||
|
||||
FFZ.settings_info.fix_color = {
|
||||
type: "select",
|
||||
options: {
|
||||
'-1': "Disabled",
|
||||
0: "Default Colors",
|
||||
1: "Luv Adjustment",
|
||||
2: "HSL Adjustment (Depreciated)",
|
||||
3: "HSV Adjustment (Depreciated)",
|
||||
4: "RGB Adjustment (Depreciated)"
|
||||
},
|
||||
value: '1',
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
||||
name: "Username Colors - Brightness",
|
||||
help: "Ensure that username colors contrast with the background enough to be readable.",
|
||||
|
||||
process_value: function(val) {
|
||||
// Load legacy setting.
|
||||
if ( val === false )
|
||||
return '0';
|
||||
else if ( val === true )
|
||||
return '1';
|
||||
return val;
|
||||
},
|
||||
|
||||
on_update: function(val) {
|
||||
document.body.classList.toggle("ffz-chat-colors", !this.has_bttv && val !== '-1');
|
||||
document.body.classList.toggle("ffz-chat-colors-gray", !this.has_bttv && (val === '-1'));
|
||||
|
||||
if ( ! this.has_bttv && val !== '-1' )
|
||||
this._rebuild_colors();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.color_blind = {
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
protanope: "Protanope",
|
||||
deuteranope: "Deuteranope",
|
||||
tritanope: "Tritanope"
|
||||
},
|
||||
value: '0',
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
||||
name: "Username Colors - Color Blindness",
|
||||
help: "Adjust username colors in an attempt to make them more distinct for people with color blindness.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( ! this.has_bttv && this.settings.fix_color !== '-1' )
|
||||
this._rebuild_colors();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// --------------------
|
||||
// Initialization
|
||||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_colors = function() {
|
||||
this.log("Preparing color-alteration style element.");
|
||||
|
||||
this._colors = {};
|
||||
|
||||
var s = this._color_style = document.createElement('style');
|
||||
s.id = 'ffz-style-username-colors';
|
||||
s.type = 'text/css';
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------
|
||||
// Color Handling Classes
|
||||
// -----------------------
|
||||
|
||||
FFZ.Color = {};
|
||||
|
||||
FFZ.Color.CVDMatrix = {
|
||||
protanope: [ // reds are greatly reduced (1% men)
|
||||
0.0, 2.02344, -2.52581,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
],
|
||||
deuteranope: [ // greens are greatly reduced (1% men)
|
||||
1.0, 0.0, 0.0,
|
||||
0.494207, 0.0, 1.24827,
|
||||
0.0, 0.0, 1.0
|
||||
],
|
||||
tritanope: [ // blues are greatly reduced (0.003% population)
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
-0.395913, 0.801109, 0.0
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
var RGBColor = FFZ.Color.RGB = function(r, g, b) {
|
||||
this.r = r||0; this.g = g||0; this.b = b||0;
|
||||
};
|
||||
|
||||
var HSVColor = FFZ.Color.HSV = function(h, s, v) {
|
||||
this.h = h||0; this.s = s||0; this.v = v||0;
|
||||
};
|
||||
|
||||
var HSLColor = FFZ.Color.HSL = function(h, s, l) {
|
||||
this.h = h||0; this.s = s||0; this.l = l||0;
|
||||
};
|
||||
|
||||
var XYZColor = FFZ.Color.XYZ = function(x, y, z) {
|
||||
this.x = x||0; this.y = y||0; this.z = z||0;
|
||||
};
|
||||
|
||||
var LUVColor = FFZ.Color.LUV = function(l, u, v) {
|
||||
this.l = l||0; this.u = u||0; this.v = v||0;
|
||||
};
|
||||
|
||||
|
||||
// RGB Colors
|
||||
|
||||
RGBColor.prototype.eq = function(rgb) {
|
||||
return rgb.r === this.r && rgb.g === this.g && rgb.b === this.b;
|
||||
}
|
||||
|
||||
RGBColor.fromHex = function(code) {
|
||||
var raw = parseInt(code.charAt(0) === '#' ? code.substr(1) : code, 16);
|
||||
return new RGBColor(
|
||||
(raw >> 16), // Red
|
||||
(raw >> 8 & 0x00FF), // Green
|
||||
(raw & 0x0000FF) // Blue
|
||||
)
|
||||
}
|
||||
|
||||
RGBColor.fromHSV = function(h, s, v) {
|
||||
var r, g, b,
|
||||
|
||||
i = Math.floor(h * 6),
|
||||
f = h * 6 - i,
|
||||
p = v * (1 - s),
|
||||
q = v * (1 - f * s),
|
||||
t = v * (1 - (1 - f) * s);
|
||||
|
||||
switch(i % 6) {
|
||||
case 0: r = v, g = t, b = p; break;
|
||||
case 1: r = q, g = v, b = p; break;
|
||||
case 2: r = p, g = v, b = t; break;
|
||||
case 3: r = p, g = q, b = v; break;
|
||||
case 4: r = t, g = p, b = v; break;
|
||||
case 5: r = v, g = p, b = q;
|
||||
}
|
||||
|
||||
return new RGBColor(
|
||||
Math.round(Math.min(Math.max(0, r*255), 255)),
|
||||
Math.round(Math.min(Math.max(0, g*255), 255)),
|
||||
Math.round(Math.min(Math.max(0, b*255), 255))
|
||||
);
|
||||
}
|
||||
|
||||
RGBColor.fromXYZ = function(x, y, z) {
|
||||
var R = 3.240479 * x - 1.537150 * y - 0.498535 * z,
|
||||
G = -0.969256 * x + 1.875992 * y + 0.041556 * z,
|
||||
B = 0.055648 * x - 0.204043 * y + 1.057311 * z;
|
||||
|
||||
// Make sure we end up in a real color space
|
||||
return new RGBColor(
|
||||
Math.max(0, Math.min(255, 255 * XYZColor.channelConverter(R))),
|
||||
Math.max(0, Math.min(255, 255 * XYZColor.channelConverter(G))),
|
||||
Math.max(0, Math.min(255, 255 * XYZColor.channelConverter(B)))
|
||||
);
|
||||
}
|
||||
|
||||
RGBColor.fromHSL = function(h, s, l) {
|
||||
if ( s === 0 ) {
|
||||
var v = Math.round(Math.min(Math.max(0, 255*l), 255));
|
||||
return new RGBColor(v, v, v);
|
||||
}
|
||||
|
||||
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
|
||||
p = 2 * l - q;
|
||||
|
||||
return new RGBColor(
|
||||
Math.round(Math.min(Math.max(0, 255 * hue2rgb(p, q, h + 1/3)), 255)),
|
||||
Math.round(Math.min(Math.max(0, 255 * hue2rgb(p, q, h)), 255)),
|
||||
Math.round(Math.min(Math.max(0, 255 * hue2rgb(p, q, h - 1/3)), 255))
|
||||
);
|
||||
}
|
||||
|
||||
RGBColor.prototype.toHSV = function() { return HSVColor.fromRGB(this.r, this.g, this.b); }
|
||||
RGBColor.prototype.toHSL = function() { return HSLColor.fromRGB(this.r, this.g, this.b); }
|
||||
RGBColor.prototype.toCSS = function() { return "rgb(" + Math.round(this.r) + "," + Math.round(this.g) + "," + Math.round(this.b) + ")"; }
|
||||
RGBColor.prototype.toXYZ = function() { return XYZColor.fromRGB(this.r, this.g, this.b); }
|
||||
RGBColor.prototype.toLUV = function() { return this.toXYZ().toLUV(); }
|
||||
|
||||
|
||||
RGBColor.prototype.luminance = function() {
|
||||
var rgb = [this.r / 255, this.g / 255, this.b / 255];
|
||||
for (var i =0, l = rgb.length; i < l; i++) {
|
||||
if (rgb[i] <= 0.03928) {
|
||||
rgb[i] = rgb[i] / 12.92;
|
||||
} else {
|
||||
rgb[i] = Math.pow( ((rgb[i]+0.055)/1.055), 2.4 );
|
||||
}
|
||||
}
|
||||
return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);
|
||||
}
|
||||
|
||||
|
||||
RGBColor.prototype.brighten = function(amount) {
|
||||
amount = typeof amount === "number" ? amount : 1;
|
||||
amount = Math.round(255 * (amount / 100));
|
||||
|
||||
return new RGBColor(
|
||||
Math.max(0, Math.min(255, this.r + amount)),
|
||||
Math.max(0, Math.min(255, this.g + amount)),
|
||||
Math.max(0, Math.min(255, this.b + amount))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
RGBColor.prototype.daltonize = function(type, amount) {
|
||||
amount = typeof amount === "number" ? amount : 1.0;
|
||||
var cvd;
|
||||
if ( typeof type === "string" ) {
|
||||
if ( FFZ.Color.CVDMatrix.hasOwnProperty(type) )
|
||||
cvd = FFZ.Color.CVDMatrix[type];
|
||||
else
|
||||
throw "Invalid CVD matrix.";
|
||||
} else
|
||||
cvd = type;
|
||||
|
||||
var cvd_a = cvd[0], cvd_b = cvd[1], cvd_c = cvd[2],
|
||||
cvd_d = cvd[3], cvd_e = cvd[4], cvd_f = cvd[5],
|
||||
cvd_g = cvd[6], cvd_h = cvd[7], cvd_i = cvd[8],
|
||||
|
||||
L, M, S, l, m, s, R, G, B, RR, GG, BB;
|
||||
|
||||
// RGB to LMS matrix conversion
|
||||
L = (17.8824 * this.r) + (43.5161 * this.g) + (4.11935 * this.b);
|
||||
M = (3.45565 * this.r) + (27.1554 * this.g) + (3.86714 * this.b);
|
||||
S = (0.0299566 * this.r) + (0.184309 * this.g) + (1.46709 * this.b);
|
||||
// Simulate color blindness
|
||||
l = (cvd_a * L) + (cvd_b * M) + (cvd_c * S);
|
||||
m = (cvd_d * L) + (cvd_e * M) + (cvd_f * S);
|
||||
s = (cvd_g * L) + (cvd_h * M) + (cvd_i * S);
|
||||
// LMS to RGB matrix conversion
|
||||
R = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
|
||||
G = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
|
||||
B = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
|
||||
// Isolate invisible colors to color vision deficiency (calculate error matrix)
|
||||
R = this.r - R;
|
||||
G = this.g - G;
|
||||
B = this.b - B;
|
||||
// Shift colors towards visible spectrum (apply error modifications)
|
||||
RR = (0.0 * R) + (0.0 * G) + (0.0 * B);
|
||||
GG = (0.7 * R) + (1.0 * G) + (0.0 * B);
|
||||
BB = (0.7 * R) + (0.0 * G) + (1.0 * B);
|
||||
// Add compensation to original values
|
||||
R = Math.min(Math.max(0, RR + this.r), 255);
|
||||
G = Math.min(Math.max(0, GG + this.g), 255);
|
||||
B = Math.min(Math.max(0, BB + this.b), 255);
|
||||
|
||||
return new RGBColor(R, G, B);
|
||||
}
|
||||
|
||||
RGBColor.prototype._r = function(r) { return new RGBColor(r, this.g, this.b); }
|
||||
RGBColor.prototype._g = function(g) { return new RGBColor(this.r, g, this.b); }
|
||||
RGBColor.prototype._b = function(b) { return new RGBColor(this.r, this.g, b); }
|
||||
|
||||
|
||||
// HSL Colors
|
||||
|
||||
HSLColor.prototype.eq = function(hsl) {
|
||||
return hsl.h === this.h && hsl.s === this.s && hsl.l === this.l;
|
||||
}
|
||||
|
||||
HSLColor.fromRGB = function(r, g, b) {
|
||||
r /= 255; g /= 255; b /= 255;
|
||||
|
||||
var max = Math.max(r,g,b),
|
||||
min = Math.min(r,g,b),
|
||||
|
||||
h, s, l = Math.min(Math.max(0, (max+min) / 2), 1),
|
||||
d = Math.min(Math.max(0, max - min), 1);
|
||||
|
||||
if ( d === 0 )
|
||||
h = s = 0;
|
||||
else {
|
||||
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;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return new HSLColor(h, s, l);
|
||||
}
|
||||
|
||||
HSLColor.prototype.toRGB = function() { return RGBColor.fromHSL(this.h, this.s, this.l); }
|
||||
HSLColor.prototype.toCSS = function() { return "hsl(" + Math.round(this.h*360) + "," + Math.round(this.s*100) + "%," + Math.round(this.l*100) + "%)"; }
|
||||
HSLColor.prototype.toHSV = function() { return RGBColor.fromHSL(this.h, this.s, this.l).toHSV(); }
|
||||
HSLColor.prototype.toXYZ = function() { return RGBColor.fromHSL(this.h, this.s, this.l).toXYZ(); }
|
||||
HSLColor.prototype.toLUV = function() { return RGBColor.fromHSL(this.h, this.s, this.l).toLUV(); }
|
||||
|
||||
|
||||
HSLColor.prototype._h = function(h) { return new HSLColor(h, this.s, this.l); }
|
||||
HSLColor.prototype._s = function(s) { return new HSLColor(this.h, s, this.l); }
|
||||
HSLColor.prototype._l = function(l) { return new HSLColor(this.h, this.s, l); }
|
||||
|
||||
|
||||
// HSV Colors
|
||||
|
||||
HSVColor.prototype.eq = function(hsv) { return hsv.h === this.h && hsv.s === this.s && hsv.v === this.v; }
|
||||
|
||||
HSVColor.fromRGB = function(r, g, b) {
|
||||
r /= 255; g /= 255; b /= 255;
|
||||
|
||||
var max = Math.max(r, g, b),
|
||||
min = Math.min(r, g, b),
|
||||
d = Math.min(Math.max(0, max - min), 1),
|
||||
|
||||
h,
|
||||
s = max === 0 ? 0 : d / max,
|
||||
v = max;
|
||||
|
||||
if ( d === 0 )
|
||||
h = 0;
|
||||
else {
|
||||
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;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return new HSVColor(h, s, v);
|
||||
}
|
||||
|
||||
|
||||
HSVColor.prototype.toRGB = function() { return RGBColor.fromHSV(this.h, this.s, this.v); }
|
||||
HSVColor.prototype.toHSL = function() { return RGBColor.fromHSV(this.h, this.s, this.v).toHSL(); }
|
||||
HSVColor.prototype.toXYZ = function() { return RGBColor.fromHSV(this.h, this.s, this.v).toXYZ(); }
|
||||
HSVColor.prototype.toLUV = function() { return RGBColor.fromHSV(this.h, this.s, this.v).toLUV(); }
|
||||
|
||||
|
||||
HSVColor.prototype._h = function(h) { return new HSVColor(h, this.s, this.v); }
|
||||
HSVColor.prototype._s = function(s) { return new HSVColor(this.h, s, this.v); }
|
||||
HSVColor.prototype._v = function(v) { return new HSVColor(this.h, this.s, v); }
|
||||
|
||||
|
||||
// XYZ Colors
|
||||
|
||||
RGBColor.channelConverter = function (channel) {
|
||||
// http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html
|
||||
// This converts rgb 8bit to rgb linear, lazy because the other algorithm is really really dumb
|
||||
return Math.pow(channel, 2.2);
|
||||
|
||||
// CSS Colors Level 4 says 0.03928, Bruce Lindbloom who cared to write all algos says 0.04045, used bruce because whynawt
|
||||
return (channel <= 0.04045) ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
|
||||
XYZColor.channelConverter = function (channel) {
|
||||
// Using lazy conversion in the other direction as well
|
||||
return Math.pow(channel, 1/2.2);
|
||||
|
||||
// I'm honestly not sure about 0.0031308, I've only seen it referenced on Bruce Lindbloom's site
|
||||
return (channel <= 0.0031308) ? channel * 12.92 : Math.pow(1.055 * channel, 1/2.4) - 0.055;
|
||||
};
|
||||
|
||||
|
||||
XYZColor.prototype.eq = function(xyz) { return xyz.x === this.x && xyz.y === this.y && xyz.z === this.z; }
|
||||
|
||||
XYZColor.fromRGB = function(r, g, b) {
|
||||
var R = RGBColor.channelConverter(r / 255),
|
||||
G = RGBColor.channelConverter(g / 255),
|
||||
B = RGBColor.channelConverter(b / 255);
|
||||
|
||||
return new XYZColor(
|
||||
0.412453 * R + 0.357580 * G + 0.180423 * B,
|
||||
0.212671 * R + 0.715160 * G + 0.072169 * B,
|
||||
0.019334 * R + 0.119193 * G + 0.950227 * B
|
||||
);
|
||||
}
|
||||
|
||||
XYZColor.fromLUV = function(l, u, v) {
|
||||
var deltaGammaFactor = 1 / (XYZColor.WHITE.x + 15 * XYZColor.WHITE.y + 3 * XYZColor.WHITE.z);
|
||||
var uDeltaGamma = 4 * XYZColor.WHITE.x * deltaGammaFactor;
|
||||
var vDeltagamma = 9 * XYZColor.WHITE.y * deltaGammaFactor;
|
||||
|
||||
// XYZColor.EPSILON * XYZColor.KAPPA = 8
|
||||
var Y = (l > 8) ? Math.pow((l + 16) / 116, 3) : l / XYZColor.KAPPA;
|
||||
|
||||
var a = 1/3 * (((52 * l) / (u + 13 * l * uDeltaGamma)) - 1);
|
||||
var b = -5 * Y;
|
||||
var c = -1/3;
|
||||
var d = Y * (((39 * l) / (v + 13 * l * vDeltagamma)) - 5);
|
||||
|
||||
var X = (d - b) / (a - c);
|
||||
var Z = X * a + b;
|
||||
|
||||
return new XYZColor(X, Y, Z);
|
||||
}
|
||||
|
||||
|
||||
XYZColor.prototype.toRGB = function() { return RGBColor.fromXYZ(this.x, this.y, this.z); }
|
||||
XYZColor.prototype.toLUV = function() { return LUVColor.fromXYZ(this.x, this.y, this.z); }
|
||||
XYZColor.prototype.toHSL = function() { return RGBColor.fromXYZ(this.x, this.y, this.z).toHSL(); }
|
||||
XYZColor.prototype.toHSV = function() { return RGBColor.fromXYZ(this.x, this.y, this.z).toHSV(); }
|
||||
|
||||
|
||||
XYZColor.prototype._x = function(x) { return new XYZColor(x, this.y, this.z); }
|
||||
XYZColor.prototype._y = function(y) { return new XYZColor(this.x, y, this.z); }
|
||||
XYZColor.prototype._z = function(z) { return new XYZColor(this.x, this.y, z); }
|
||||
|
||||
|
||||
// LUV Colors
|
||||
|
||||
XYZColor.EPSILON = Math.pow(6 / 29, 3);
|
||||
XYZColor.KAPPA = Math.pow(29 / 3, 3);
|
||||
XYZColor.WHITE = (new RGBColor(255, 255, 255)).toXYZ();
|
||||
|
||||
|
||||
LUVColor.prototype.eq = function(luv) { return luv.l === this.l && luv.u === this.u && luv.v === this.v; }
|
||||
|
||||
LUVColor.fromXYZ = function(X, Y, Z) {
|
||||
var deltaGammaFactor = 1 / (XYZColor.WHITE.x + 15 * XYZColor.WHITE.y + 3 * XYZColor.WHITE.z);
|
||||
var uDeltaGamma = 4 * XYZColor.WHITE.x * deltaGammaFactor;
|
||||
var vDeltagamma = 9 * XYZColor.WHITE.y * deltaGammaFactor;
|
||||
|
||||
var yGamma = Y / XYZColor.WHITE.y;
|
||||
var deltaDivider = (X + 15 * Y + 3 * Z);
|
||||
|
||||
if (deltaDivider === 0) {
|
||||
deltaDivider = 1;
|
||||
}
|
||||
|
||||
var deltaFactor = 1 / deltaDivider;
|
||||
|
||||
var uDelta = 4 * X * deltaFactor;
|
||||
var vDelta = 9 * Y * deltaFactor;
|
||||
|
||||
var L = (yGamma > XYZColor.EPSILON) ? 116 * Math.pow(yGamma, 1/3) - 16 : XYZColor.KAPPA * yGamma;
|
||||
var u = 13 * L * (uDelta - uDeltaGamma);
|
||||
var v = 13 * L * (vDelta - vDeltagamma);
|
||||
|
||||
return new LUVColor(L, u, v);
|
||||
}
|
||||
|
||||
|
||||
LUVColor.prototype.toXYZ = function() { return XYZColor.fromLUV(this.l, this.u, this.v); }
|
||||
LUVColor.prototype.toRGB = function() { return XYZColor.fromLUV(this.l, this.u, this.v).toRGB(); }
|
||||
LUVColor.prototype.toHSL = function() { return XYZColor.fromLUV(this.l, this.u, this.v).toHSL(); }
|
||||
LUVColor.prototype.toHSV = function() { return XYZColor.fromLUV(this.l, this.u, this.v).toHSV(); }
|
||||
|
||||
|
||||
LUVColor.prototype._l = function(l) { return new LUVColor(l, this.u, this.v); }
|
||||
LUVColor.prototype._u = function(u) { return new LUVColor(this.l, u, this.v); }
|
||||
LUVColor.prototype._v = function(v) { return new LUVColor(this.l, this.u, v); }
|
||||
|
||||
|
||||
// Required Colors
|
||||
|
||||
var REQUIRED_CONTRAST = 4.5,
|
||||
|
||||
REQUIRED_BRIGHT = new XYZColor(0, (REQUIRED_CONTRAST * (new RGBColor(35,35,35).toXYZ().y + 0.05) - 0.05), 0).toLUV().l,
|
||||
REQUIRED_DARK = new XYZColor(0, ((new RGBColor(217,217,217).toXYZ().y + 0.05) / REQUIRED_CONTRAST - 0.05), 0).toLUV().l;
|
||||
|
||||
|
||||
// --------------------
|
||||
// Rebuild Colors
|
||||
// --------------------
|
||||
|
||||
FFZ.prototype._rebuild_colors = function() {
|
||||
if ( ! this._color_style || this.has_bttv )
|
||||
return;
|
||||
|
||||
this._color_style.innerHTML = '';
|
||||
var colors = Object.keys(this._colors);
|
||||
this._colors = {};
|
||||
for(var i=0, l=colors.length; i<l; i++)
|
||||
this._handle_color(colors[i]);
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._handle_color = function(color) {
|
||||
if ( ! color || this._colors.hasOwnProperty(color) )
|
||||
return;
|
||||
|
||||
this._colors[color] = true;
|
||||
var rgb = RGBColor.fromHex(color),
|
||||
|
||||
clr = color,
|
||||
light_color = color,
|
||||
dark_color = color,
|
||||
matched = false,
|
||||
rule = 'span[style="color:' + color + '"]';
|
||||
|
||||
|
||||
// Color Blindness Handling
|
||||
if ( this.settings.color_blind !== '0' ) {
|
||||
var new_color = rgb.daltonize(this.settings.color_blind);
|
||||
if ( ! rgb.eq(new_color) ) {
|
||||
rgb = new_color;
|
||||
clr = light_color = dark_color = rgb.toCSS();
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Color Processing - RGB
|
||||
if ( this.settings.fix_color === '4' ) {
|
||||
var lum = rgb.luminance();
|
||||
|
||||
if ( lum > 0.3 ) {
|
||||
var s = 127, nc = rgb;
|
||||
while(s--) {
|
||||
nc = nc.brighten(-1);
|
||||
if ( nc.luminance() <= 0.3 )
|
||||
break;
|
||||
}
|
||||
|
||||
matched = true;
|
||||
light_color = nc.toCSS();
|
||||
}
|
||||
|
||||
if ( lum < 0.15 ) {
|
||||
var s = 127, nc = rgb;
|
||||
while(s--) {
|
||||
nc = nc.brighten();
|
||||
if ( nc.luminance() >= 0.15 )
|
||||
break;
|
||||
}
|
||||
|
||||
matched = true;
|
||||
dark_color = nc.toCSS();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Color Processing - HSL
|
||||
if ( this.settings.fix_color === '2' ) {
|
||||
var hsl = rgb.toHSL();
|
||||
|
||||
matched = true;
|
||||
light_color = hsl._l(Math.min(Math.max(0, 0.7 * hsl.l), 1)).toCSS();
|
||||
dark_color = hsl._l(Math.min(Math.max(0, 0.3 + (0.7 * hsl.l)), 1)).toCSS();
|
||||
}
|
||||
|
||||
|
||||
// Color Processing - HSV
|
||||
if ( this.settings.fix_color === '3' ) {
|
||||
var hsv = rgb.toHSV();
|
||||
matched = true;
|
||||
|
||||
if ( hsv.s === 0 ) {
|
||||
// Black and White
|
||||
light_color = hsv._v(Math.min(Math.max(0.5, 0.5 * hsv.v), 1)).toRGB().toCSS();
|
||||
dark_color = hsv._v(Math.min(Math.max(0.5, 0.5 + (0.5 * hsv.v)), 1)).toRGB().toCSS();
|
||||
|
||||
} else {
|
||||
light_color = RGBColor.fromHSV(hsv.h, Math.min(Math.max(0.7, 0.7 + (0.3 * hsv.s)), 1), Math.min(0.7, hsv.v)).toCSS();
|
||||
dark_color = RGBColor.fromHSV(hsv.h, Math.min(0.7, hsv.s), Math.min(Math.max(0.7, 0.7 + (0.3 * hsv.v)), 1)).toCSS();
|
||||
}
|
||||
}
|
||||
|
||||
// Color Processing - LUV
|
||||
if ( this.settings.fix_color === '1' ) {
|
||||
var luv = rgb.toLUV();
|
||||
|
||||
if ( luv.l > REQUIRED_DARK ) {
|
||||
matched = true;
|
||||
light_color = luv._l(REQUIRED_DARK).toRGB().toCSS();
|
||||
}
|
||||
|
||||
if ( luv.l < REQUIRED_BRIGHT ) {
|
||||
matched = true;
|
||||
dark_color = luv._l(REQUIRED_BRIGHT).toRGB().toCSS();
|
||||
}
|
||||
}
|
||||
|
||||
// Output
|
||||
if ( ! matched )
|
||||
return;
|
||||
|
||||
var output = '';
|
||||
|
||||
if ( light_color !== clr )
|
||||
output += 'body.ffz-chat-colors .chat-line ' + rule + ' { color: ' + light_color + ' !important; }';
|
||||
|
||||
if ( dark_color !== light_color ) {
|
||||
output += 'body.ffz-chat-colors .theatre .chat-container .chat-line ' + rule +
|
||||
', body.ffz-chat-colors .ember-chat-container.dark .chat-line ' + rule +
|
||||
', body.ffz-chat-colors .ember-chat-container.force-dark .chat-line ' + rule +
|
||||
', body.ffz-chat-colors .chat-container.dark .chat-line ' + rule +
|
||||
', body.ffz-chat-colors .chat-container.force-dark .chat-line ' + rule + ' { color: ' + dark_color + ' !important; }';
|
||||
}
|
||||
|
||||
this._color_style.innerHTML += output;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue