move getRealColors to colorpicker and reuse it
This commit is contained in:
parent
97e486e139
commit
fd047f8323
|
@ -1,4 +1,4 @@
|
||||||
/* global regExpTester debounce messageBox CodeMirror template */
|
/* global regExpTester debounce messageBox CodeMirror template colorMimicry */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function createAppliesToLineWidget(cm) {
|
function createAppliesToLineWidget(cm) {
|
||||||
|
@ -214,13 +214,13 @@ function createAppliesToLineWidget(cm) {
|
||||||
const MIN_LUMA = .05;
|
const MIN_LUMA = .05;
|
||||||
const MIN_LUMA_DIFF = .4;
|
const MIN_LUMA_DIFF = .4;
|
||||||
const color = {
|
const color = {
|
||||||
wrapper: getRealColors(cm.display.wrapper),
|
wrapper: colorMimicry.get(cm.display.wrapper),
|
||||||
gutter: getRealColors(cm.display.gutters, {
|
gutter: colorMimicry.get(cm.display.gutters, {
|
||||||
bg: 'backgroundColor',
|
bg: 'backgroundColor',
|
||||||
border: 'borderRightColor',
|
border: 'borderRightColor',
|
||||||
}),
|
}),
|
||||||
line: getRealColors('.CodeMirror-linenumber'),
|
line: colorMimicry.get('.CodeMirror-linenumber', null, cm.display.lineDiv),
|
||||||
comment: getRealColors('span.cm-comment'),
|
comment: colorMimicry.get('span.cm-comment', null, cm.display.lineDiv),
|
||||||
};
|
};
|
||||||
const hasBorder =
|
const hasBorder =
|
||||||
color.gutter.style.borderRightWidth !== '0px' &&
|
color.gutter.style.borderRightWidth !== '0px' &&
|
||||||
|
@ -258,65 +258,11 @@ function createAppliesToLineWidget(cm) {
|
||||||
fill: ${fore};
|
fill: ${fore};
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
.applies-to button {
|
||||||
|
color: ${fore};
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
document.documentElement.appendChild(actualStyle);
|
document.documentElement.appendChild(actualStyle);
|
||||||
|
|
||||||
function getRealColors(el, targets = {}) {
|
|
||||||
targets.fore = 'color';
|
|
||||||
const colors = {};
|
|
||||||
const done = {};
|
|
||||||
let numDone = 0;
|
|
||||||
let numTotal = 0;
|
|
||||||
for (const k in targets) {
|
|
||||||
colors[k] = {r: 255, g: 255, b: 255, a: 1};
|
|
||||||
numTotal++;
|
|
||||||
}
|
|
||||||
const isDummy = typeof el === 'string';
|
|
||||||
el = isDummy ? cm.display.lineDiv.appendChild($create(el, {style: 'display: none'})) : el;
|
|
||||||
for (let current = el; current; current = current && current.parentElement) {
|
|
||||||
const style = getComputedStyle(current);
|
|
||||||
for (const k in targets) {
|
|
||||||
if (!done[k]) {
|
|
||||||
done[k] = blend(colors[k], style[targets[k]]);
|
|
||||||
numDone += done[k] ? 1 : 0;
|
|
||||||
if (numDone === numTotal) {
|
|
||||||
current = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
colors.style = colors.style || style;
|
|
||||||
}
|
|
||||||
if (isDummy) {
|
|
||||||
el.remove();
|
|
||||||
}
|
|
||||||
for (const k in targets) {
|
|
||||||
const {r, g, b, a} = colors[k];
|
|
||||||
colors[k] = `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
||||||
// https://www.w3.org/TR/AERT#color-contrast
|
|
||||||
colors[k + 'Luma'] = (r * .299 + g * .587 + b * .114) / 256;
|
|
||||||
}
|
|
||||||
return colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
function blend(base, color) {
|
|
||||||
const [r, g, b, a = 255] = (color.match(/\d+/g) || []).map(Number);
|
|
||||||
if (a === 255) {
|
|
||||||
base.r = r;
|
|
||||||
base.g = g;
|
|
||||||
base.b = b;
|
|
||||||
base.a = 1;
|
|
||||||
} else if (a) {
|
|
||||||
const mixedA = 1 - (1 - a / 255) * (1 - base.a);
|
|
||||||
const q1 = a / 255 / mixedA;
|
|
||||||
const q2 = base.a * (1 - mixedA) / mixedA;
|
|
||||||
base.r = Math.round(r * q1 + base.r * q2);
|
|
||||||
base.g = Math.round(g * q1 + base.g * q2);
|
|
||||||
base.b = Math.round(b * q1 + base.b * q2);
|
|
||||||
base.a = mixedA;
|
|
||||||
}
|
|
||||||
return Math.abs(base.a - 1) < 1e-3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doUpdate() {
|
function doUpdate() {
|
||||||
|
|
|
@ -932,30 +932,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function guessTheme() {
|
function guessTheme() {
|
||||||
const realColor = {r: 255, g: 255, b: 255, a: 1};
|
const el = options.guessBrightness ||
|
||||||
const start = options.guessBrightness ||
|
((cm.display.renderedView || [])[0] || {}).text ||
|
||||||
((cm.display.renderedView || [])[0] || {}).text || cm.display.lineDiv;
|
cm.display.lineDiv;
|
||||||
for (let el = start; el; el = el.parentElement) {
|
const bgLuma = window.colorMimicry.get(el, {bg: 'backgroundColor'}).bgLuma;
|
||||||
const bgColor = getComputedStyle(el).backgroundColor;
|
return bgLuma < .5 ? 'dark' : 'light';
|
||||||
const [r, g, b, a = 255] = (bgColor.match(/\d+/g) || []).map(Number);
|
|
||||||
if (!a) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const mixedA = 1 - (1 - a / 255) * (1 - realColor.a);
|
|
||||||
const q1 = a / 255 / mixedA;
|
|
||||||
const q2 = realColor.a * (1 - mixedA) / mixedA;
|
|
||||||
realColor.r = Math.round(r * q1 + realColor.r * q2);
|
|
||||||
realColor.g = Math.round(g * q1 + realColor.g * q2);
|
|
||||||
realColor.b = Math.round(b * q1 + realColor.b * q2);
|
|
||||||
realColor.a = mixedA;
|
|
||||||
if (Math.abs(realColor.a - 1) < 1e-3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// https://www.w3.org/TR/AERT#color-contrast
|
|
||||||
const {r, g, b} = realColor;
|
|
||||||
const brightness = r * .299 + g * .587 + b * .114;
|
|
||||||
return brightness < 128 ? 'dark' : 'light';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function constrain(min, max, value) {
|
function constrain(min, max, value) {
|
||||||
|
@ -979,3 +960,92 @@
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var colorMimicry = (() => {
|
||||||
|
const styleCache = new Map();
|
||||||
|
return {get};
|
||||||
|
|
||||||
|
// Calculates real color of an element:
|
||||||
|
// colorMimicry.get(cm.display.gutters, {bg: 'backgroundColor'})
|
||||||
|
// colorMimicry.get('input.foo.bar', null, $('some.parent.to.host.the.dummy'))
|
||||||
|
function get(el, targets, dummyContainer = document.body) {
|
||||||
|
targets = targets || {};
|
||||||
|
targets.fore = 'color';
|
||||||
|
const colors = {};
|
||||||
|
const done = {};
|
||||||
|
let numDone = 0;
|
||||||
|
let numTotal = 0;
|
||||||
|
const rootStyle = getStyle(document.documentElement);
|
||||||
|
for (const k in targets) {
|
||||||
|
const base = {r: 255, g: 255, b: 255, a: 1};
|
||||||
|
blend(base, rootStyle[targets[k]]);
|
||||||
|
colors[k] = base;
|
||||||
|
numTotal++;
|
||||||
|
}
|
||||||
|
const isDummy = typeof el === 'string';
|
||||||
|
if (isDummy) {
|
||||||
|
el = dummyContainer.appendChild($create(el, {style: 'display: none'}));
|
||||||
|
}
|
||||||
|
for (let current = el; current; current = current && current.parentElement) {
|
||||||
|
const style = getStyle(current);
|
||||||
|
for (const k in targets) {
|
||||||
|
if (!done[k]) {
|
||||||
|
done[k] = blend(colors[k], style[targets[k]]);
|
||||||
|
numDone += done[k] ? 1 : 0;
|
||||||
|
if (numDone === numTotal) {
|
||||||
|
current = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colors.style = colors.style || style;
|
||||||
|
}
|
||||||
|
if (isDummy) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
for (const k in targets) {
|
||||||
|
const {r, g, b, a} = colors[k];
|
||||||
|
colors[k] = `rgba(${r}, ${g}, ${b}, ${a})`;
|
||||||
|
// https://www.w3.org/TR/AERT#color-contrast
|
||||||
|
colors[k + 'Luma'] = (r * .299 + g * .587 + b * .114) / 256;
|
||||||
|
}
|
||||||
|
debounce(clearCache);
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
function blend(base, color) {
|
||||||
|
const [r, g, b, a = 255] = (color.match(/\d+/g) || []).map(Number);
|
||||||
|
if (a === 255) {
|
||||||
|
base.r = r;
|
||||||
|
base.g = g;
|
||||||
|
base.b = b;
|
||||||
|
base.a = 1;
|
||||||
|
} else if (a) {
|
||||||
|
const mixedA = 1 - (1 - a / 255) * (1 - base.a);
|
||||||
|
const q1 = a / 255 / mixedA;
|
||||||
|
const q2 = base.a * (1 - mixedA) / mixedA;
|
||||||
|
base.r = Math.round(r * q1 + base.r * q2);
|
||||||
|
base.g = Math.round(g * q1 + base.g * q2);
|
||||||
|
base.b = Math.round(b * q1 + base.b * q2);
|
||||||
|
base.a = mixedA;
|
||||||
|
}
|
||||||
|
return Math.abs(base.a - 1) < 1e-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// speed-up for sequential invocations within the same event loop cycle
|
||||||
|
// (we're assuming the invoker doesn't force CSSOM to refresh between the calls)
|
||||||
|
function getStyle(el) {
|
||||||
|
let style = styleCache.get(el);
|
||||||
|
if (!style) {
|
||||||
|
style = getComputedStyle(el);
|
||||||
|
styleCache.set(el, style);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCache() {
|
||||||
|
styleCache.clear();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user