create minified color names module
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
### Fixture for 11 color names
|
||||
|
||||
`rgb.txt` contains X11's defined color names, copied over from `/etc/X11/rgb.txt` on Ubuntu 18.
|
||||
|
||||
Run `create_module.js` to create a TS module containing the color definitions. The script performs these steps:
|
||||
- extract color definitions from `rgb.txt`
|
||||
- remove gray definitions (re-added programmatically later)
|
||||
- create a perfect hash function
|
||||
- calculate crc10 for basic collision prevention
|
||||
- run several collision tests
|
||||
- compress table and color data
|
||||
- write data with loading shim to `ColorNames.ts`
|
||||
|
||||
The final file is meant to be copied over to `../../src/common/data/`.
|
||||
@@ -0,0 +1,447 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* For decoder side:
|
||||
* - reconstruct grays with f = lambda x: (x * 256 - x + 50) / 100 (needs value rounding check)
|
||||
* - apply nameFilter
|
||||
* - build lookup & extract functions (runtime decoding?)
|
||||
* - transfer hashtable and color table
|
||||
*/
|
||||
|
||||
// match color entry in rgb.txt
|
||||
const rexFile = /^\s*(\d+)\s*(\d+)\s*(\d+)\s*?[\t]+(.*)$/;
|
||||
// match greyXX|grayXX names
|
||||
const rexGrey = /^gr[ae]y\d+/;
|
||||
// name match
|
||||
const rexName = /^\w?[A-Za-z0-9 ]+\w/;
|
||||
|
||||
function parseX11Colors(filename) {
|
||||
const fileData = fs.readFileSync(filename, {encoding: 'utf8'});
|
||||
const colors = [];
|
||||
for (const line of fileData.split('\n')) {
|
||||
const m = rexFile.exec(line);
|
||||
if (m) {
|
||||
colors.push({
|
||||
color: [parseInt(m[1]), parseInt(m[2]), parseInt(m[3])],
|
||||
name: m[4]
|
||||
});
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
// Use the FNV algorithm from http://isthe.com/chongo/tech/comp/fnv/
|
||||
function hash(d, name) {
|
||||
if (!d) d = 0x01000193;
|
||||
for (const c of name) {
|
||||
d = ( (d * 0x01000193) ^ c.charCodeAt(0) ) & 0xffffffff;
|
||||
}
|
||||
return d >>> 0;
|
||||
}
|
||||
|
||||
// inspired from http://stevehanov.ca/blog/?id=119
|
||||
function createMinimalPerfectHash(nameList) {
|
||||
const nameMap = Object.create(null);
|
||||
for (const [idx, name] of nameList.entries()) {
|
||||
nameMap[name] = idx;
|
||||
}
|
||||
const size = nameList.length;
|
||||
|
||||
const buckets = [];
|
||||
for (let i = 0; i < size; ++i) buckets.push([]);
|
||||
const g = new Array(size).fill(0);
|
||||
const v = new Array(size).fill(null);
|
||||
|
||||
for (const key of nameList) {
|
||||
buckets[hash(0, key) % size].push(key);
|
||||
}
|
||||
|
||||
buckets.sort((a, b) => b.length - a.length);
|
||||
let breakIdx = 0;
|
||||
for (let i = 0; i < size; ++i) {
|
||||
const bucket = buckets[i];
|
||||
if (bucket.length <= 1) {
|
||||
breakIdx = i;
|
||||
break;
|
||||
}
|
||||
let d = 1;
|
||||
let item = 0;
|
||||
let slots = [];
|
||||
|
||||
while (item < bucket.length) {
|
||||
const slot = hash(d, bucket[item]) % size;
|
||||
if (v[slot] !== null || slots.includes(slot)) {
|
||||
d++;
|
||||
item = 0;
|
||||
slots = [];
|
||||
} else {
|
||||
slots.push(slot);
|
||||
item++;
|
||||
}
|
||||
}
|
||||
|
||||
g[hash(0, bucket[0]) % size] = d;
|
||||
for (let k = 0; k < bucket.length; ++k) {
|
||||
v[slots[k]] = nameMap[bucket[k]];
|
||||
}
|
||||
}
|
||||
|
||||
const freeList = [];
|
||||
for (let i = 0; i < size; ++i) {
|
||||
if (v[i] === null) freeList.push(i);
|
||||
}
|
||||
|
||||
for (let i = breakIdx; i < size; ++i) {
|
||||
const bucket = buckets[i];
|
||||
if (!bucket.length) break;
|
||||
const slot = freeList.pop();
|
||||
g[hash(0, bucket[0]) % size] = -slot - 1;
|
||||
v[slot] = nameMap[bucket[0]];
|
||||
}
|
||||
|
||||
return [g, v];
|
||||
}
|
||||
|
||||
function lookupPerfectHash(g, v, key) {
|
||||
const d = g[hash(0, key) % g.length];
|
||||
if (d < 0) return v[-d - 1];
|
||||
return v[hash(d, key) % v.length];
|
||||
}
|
||||
|
||||
function checkPerfectHashTables(g, v, nameList) {
|
||||
let allPassed = true;
|
||||
for (const [idx, name] of nameList.entries()) {
|
||||
const lookup = lookupPerfectHash(g, v, name);
|
||||
if (lookup !== idx) {
|
||||
console.log(`\x1b[33mmismatch: '${name}' returns ${lookup} (orig: ${idx})\x1b[m`);
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
return allPassed;
|
||||
}
|
||||
|
||||
function crc10atm(name, crc) {
|
||||
if (!crc) crc = 0;
|
||||
for (const c of name) {
|
||||
const v = c.charCodeAt(0);
|
||||
crc ^= v << 2;
|
||||
for (let k = 0; k < 8; k++) {
|
||||
crc = crc & 0x200 ? (crc << 1) ^ 0x233 : crc << 1;
|
||||
}
|
||||
}
|
||||
crc &= 0x3ff;
|
||||
return crc >>> 0;
|
||||
}
|
||||
|
||||
function checkColorList(g, v, crc, colorNames) {
|
||||
let match = [];
|
||||
for (const word of colorNames) {
|
||||
if (!nameFilter(word)) continue;
|
||||
const idx = lookupPerfectHash(g, v, word);
|
||||
const crc10 = crc10atm(word);
|
||||
if (crc[idx] === crc10) {
|
||||
match.push({idx, word, colorName: colorNames[idx]});
|
||||
}
|
||||
}
|
||||
return {tested: colorNames.length, match};
|
||||
}
|
||||
|
||||
function checkWordlists(g, v, crc, colorNames, filename) {
|
||||
const fileData = fs.readFileSync(filename, {encoding: 'utf8'});
|
||||
const words = fileData.split('\n').filter(el => lookupPerfectHash.length !== 0);
|
||||
let collisions = [];
|
||||
for (const word of words) {
|
||||
if (!nameFilter(word)) continue;
|
||||
const idx = lookupPerfectHash(g, v, word);
|
||||
const crc10 = crc10atm(word);
|
||||
if (crc[idx] === crc10 && word !== colorNames[idx]) {
|
||||
collisions.push({idx, word, colorName: colorNames[idx]});
|
||||
}
|
||||
}
|
||||
return {tested: words.length, collisions};
|
||||
}
|
||||
|
||||
function nameFilter(name) {
|
||||
// length 3 - 22
|
||||
if (name.length < 3 || name.length > 22) return;
|
||||
// chars only in [A-Za-z0-9 ]
|
||||
if (!rexName.exec(name)) return;
|
||||
return name;
|
||||
}
|
||||
|
||||
function compressTables(g, v, crc, al) {
|
||||
// g | v | crc: all in 10 bit (<1024)
|
||||
// --> 30 bit
|
||||
// --> fits into 5 bytes of a 64-bit char alphabet
|
||||
|
||||
// g needs an offset for proper zero alignment
|
||||
const gOffset = -Math.min(...g);
|
||||
g = g.map(el => el + gOffset);
|
||||
|
||||
// assert we are in 0..2^10
|
||||
if (Math.min(...g) < 0 || Math.min(...v) < 0 || Math.min(...crc) < 0
|
||||
|| Math.max(...g) > 1023 || Math.max(...v) > 1023 || Math.max(...crc) > 1023
|
||||
) {
|
||||
console.log('\x1b[31mTables out of compressible range, manual fix needed.\x1b[m');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// assert we have same length
|
||||
if (g.length !== v.length || g.length !== crc.length) {
|
||||
console.log('\x1b[31mTables length mismatch, manual fix needed.\x1b[m');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// construct compressed data string
|
||||
let result = '';
|
||||
const length = g.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let value = (g[i] << 20) | (v[i] << 10) | crc[i];
|
||||
let bucket = '';
|
||||
for (let k = 0; k < 5; ++k) {
|
||||
bucket += al[value % al.length];
|
||||
value = Math.floor(value / al.length);
|
||||
}
|
||||
result += bucket.split('').reverse().join('');
|
||||
}
|
||||
|
||||
return [result, length, gOffset];
|
||||
}
|
||||
|
||||
function compressColors(colors, al) {
|
||||
let result = '';
|
||||
for (const color of colors) {
|
||||
let value = (color[0] << 16) | (color[1] << 8) | color[2];
|
||||
let bucket = '';
|
||||
for (let k = 0; k < 4; ++k) {
|
||||
bucket += al[value % al.length];
|
||||
value = Math.floor(value / al.length);
|
||||
}
|
||||
result += bucket.split('').reverse().join('');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function loadData(bucket, al) {
|
||||
let value = 0;
|
||||
for (const c of bucket) {
|
||||
value *= al.length;
|
||||
value += al.indexOf(c);
|
||||
}
|
||||
return [value >>> 20, (value >> 10) & 0x3FF, value & 0x3FF];
|
||||
}
|
||||
|
||||
function loadColor(al, data, idx) {
|
||||
// color buckets are hardcoded to 4 chars
|
||||
let value = 0;
|
||||
for (let i = idx * 4; i < idx * 4 + 4; ++i) {
|
||||
value *= al.length;
|
||||
value += al.indexOf(data[i]);
|
||||
}
|
||||
return [value >>> 16, (value >> 8) & 0xFF, value & 0xFF];
|
||||
}
|
||||
|
||||
function lookupIdx(al, data, length, gOffset, name) {
|
||||
const bl = data.length / length;
|
||||
let offset = (hash(0, name) % length) * bl;
|
||||
let [g, v, crc] = loadData(data.slice(offset, offset + bl), al);
|
||||
offset = g < gOffset
|
||||
? (-(g - gOffset) - 1) * bl
|
||||
: (hash(g - gOffset, name) % length) * bl;
|
||||
[_, v, _] = loadData(data.slice(offset, offset + bl), al);
|
||||
offset = v * bl;
|
||||
[_, _, crc] = loadData(data.slice(offset, offset + bl), al);
|
||||
return crc10atm(name) === crc ? v : -1;
|
||||
}
|
||||
|
||||
function lookup(al, data, colorData, length, gOffset, name) {
|
||||
const idx = lookupIdx(al, data, length, gOffset, name);
|
||||
if (idx === -1) return;
|
||||
return loadColor(al, colorData, idx);
|
||||
}
|
||||
|
||||
function createModule(tableData, colorData, alphabet, gOffset, length) {
|
||||
const TMPL = `/**
|
||||
* Copyright (c) 2021 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* This module enables X11 color name lookups with the help of a perfect hash function
|
||||
* to not penalize the package size too much.
|
||||
* saving: ~70% (from 17kB down to 5kB)
|
||||
*/
|
||||
|
||||
// Note: module and table data created with fixtures/x11-colornames/create_module.js
|
||||
const TABLE = '${tableData}';
|
||||
const COLORS = '${colorData}';
|
||||
const ALPHABET = '${alphabet}';
|
||||
const OFFSET = ${gOffset};
|
||||
const LENGTH = ${length};
|
||||
const BUCKET_LENGTH = TABLE.length / LENGTH;
|
||||
|
||||
// match greyXX|grayXX names
|
||||
const rexGrey = /^gr[ae]y(\\d+)/;
|
||||
// name match
|
||||
const rexName = /^\\w?[A-Za-z0-9 ]+\\w/;
|
||||
|
||||
function gray(n: number): [number, number, number] | undefined {
|
||||
if (0 <= n && n <= 100) {
|
||||
const v = Math.floor((n * 256 - n + 50) / 100);
|
||||
return [v, v, v];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function hash(d: number, name: string): number {
|
||||
if (!d) d = 0x01000193;
|
||||
for (const c of name) {
|
||||
d = ((d * 0x01000193) ^ c.charCodeAt(0)) & 0xffffffff;
|
||||
}
|
||||
return d >>> 0;
|
||||
}
|
||||
|
||||
function crc10(name: string, crc?: number): number {
|
||||
if (!crc) crc = 0;
|
||||
for (const c of name) {
|
||||
crc ^= c.charCodeAt(0) << 2;
|
||||
for (let k = 0; k < 8; k++) {
|
||||
crc = crc & 0x200 ? (crc << 1) ^ 0x233 : crc << 1;
|
||||
}
|
||||
}
|
||||
crc &= 0x3ff;
|
||||
return crc >>> 0;
|
||||
}
|
||||
|
||||
function loadData(idx: number): [number, number, number] {
|
||||
let value = 0;
|
||||
for (let i = idx * BUCKET_LENGTH; i < idx * BUCKET_LENGTH + BUCKET_LENGTH; ++i) {
|
||||
value *= ALPHABET.length;
|
||||
value += ALPHABET.indexOf(TABLE[i]);
|
||||
}
|
||||
return [value >>> 20, (value >> 10) & 0x3FF, value & 0x3FF];
|
||||
}
|
||||
|
||||
function loadColor(idx: number): [number, number, number] {
|
||||
// color buckets are hardcoded to 4 chars
|
||||
let v = 0;
|
||||
for (let i = idx * 4; i < idx * 4 + 4; ++i) {
|
||||
v *= ALPHABET.length;
|
||||
v += ALPHABET.indexOf(COLORS[i]);
|
||||
}
|
||||
return [v >>> 16, (v >> 8) & 0xFF, v & 0xFF];
|
||||
}
|
||||
|
||||
function lookupIdx(name: string): number {
|
||||
let b = loadData(hash(0, name) % LENGTH);
|
||||
b = loadData(b[0] < OFFSET ? (-(b[0] - OFFSET) - 1) : hash(b[0] - OFFSET, name) % LENGTH);
|
||||
const [ , , crc] = loadData(b[1]);
|
||||
return crc10(name) === crc ? b[1] : -1;
|
||||
}
|
||||
|
||||
export function getColorFromName(name: string): [number, number, number] | undefined {
|
||||
// basic name filtering
|
||||
if (name.length < 3 || name.length > 22 || !rexName.exec(name)) return;
|
||||
|
||||
// handle grays special
|
||||
const m = rexGrey.exec(name);
|
||||
if (m) return gray(parseInt(m[1]));
|
||||
|
||||
// grab crc checked idx from PHF
|
||||
const idx = lookupIdx(name);
|
||||
if (idx === -1) return;
|
||||
return loadColor(idx);
|
||||
}
|
||||
`;
|
||||
return TMPL;
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
// parse definitions from X11 file
|
||||
const colorList = parseX11Colors(path.join(__dirname, '/rgb.txt'))
|
||||
.filter(el => !rexGrey.exec(el.name)); // remove greys, as we can reconstruct them later
|
||||
const nameList = colorList.map(el => el.name);
|
||||
|
||||
// PHF creation and test
|
||||
const [g, v] = createMinimalPerfectHash(nameList);
|
||||
if (!checkPerfectHashTables(g, v, nameList)) {
|
||||
console.error('\x1b[31mPHF creation failed.\x1b[m');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('\x1b[32mPHF creation successful.\x1b[m');
|
||||
}
|
||||
|
||||
// calc 10-bit CRCs to rule to avoid collisions at ~1:1024
|
||||
const crc = nameList.map(el => crc10atm(el));
|
||||
|
||||
// collision check against colorNames - must all collide
|
||||
console.log('Self collision test:')
|
||||
const collSelf = checkColorList(g, v, crc, nameList);
|
||||
console.log('self:', {
|
||||
entries: collSelf.tested,
|
||||
matches: collSelf.match.length,
|
||||
rate: collSelf.tested / collSelf.match.length
|
||||
});
|
||||
if (collSelf.match.length !== collSelf.tested) {
|
||||
console.error('\x1b[31mSelf collision tested failed.\x1b[m');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// basic collision checks against dictionaries (rates should be greater than 900:1)
|
||||
console.log('Dictionary collision test:')
|
||||
const collEnglish = checkWordlists(g, v, crc, nameList, '/usr/share/dict/words');
|
||||
console.log('english:', {
|
||||
entries: collEnglish.tested,
|
||||
collisions: collEnglish.collisions.length,
|
||||
rate: collEnglish.tested / collEnglish.collisions.length
|
||||
});
|
||||
//console.log(collEnglish.collisions);
|
||||
const collnGerman = checkWordlists(g, v, crc, nameList, '/usr/share/dict/ngerman');
|
||||
console.log('ngerman:', {
|
||||
entries: collnGerman.tested,
|
||||
collisions: collnGerman.collisions.length,
|
||||
rate: collnGerman.tested / collnGerman.collisions.length
|
||||
});
|
||||
const colloGerman = checkWordlists(g, v, crc, nameList, '/usr/share/dict/ogerman');
|
||||
console.log('ogerman:', {
|
||||
entries: colloGerman.tested,
|
||||
collisions: colloGerman.collisions.length,
|
||||
rate: colloGerman.tested / colloGerman.collisions.length
|
||||
});
|
||||
|
||||
// compression with custom alphabet
|
||||
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!?';
|
||||
const [tableData, length, gOffset] = compressTables(g, v, crc, ALPHABET);
|
||||
const colorData = compressColors(colorList.map(el => el.color), ALPHABET);
|
||||
|
||||
// test loading of compressed table data
|
||||
let failed = false;
|
||||
for (const name of nameList) {
|
||||
const orig = lookupPerfectHash(g, v, name);
|
||||
const idx = lookupIdx(ALPHABET, tableData, length, gOffset, name);
|
||||
if (idx !== orig) {
|
||||
console.log('\x1b[31mcompressed loading failed for:\x1b[m', {name, idx, orig});
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
if (failed) process.exit(1);
|
||||
|
||||
// test full color decoding
|
||||
for (const color of colorList) {
|
||||
const loaded = lookup(ALPHABET, tableData, colorData, length, gOffset, color.name);
|
||||
if (loaded[0] !== color.color[0] || loaded[1] !== color.color[1] || loaded[2] !== color.color[2]) {
|
||||
console.log('\x1b[31mcolor loading failed for:\x1b[m', {color, loaded});
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
if (failed) process.exit(1);
|
||||
|
||||
// if we made it up to here, create decoding boilerplate
|
||||
const moduleData = createModule(tableData, colorData, ALPHABET, gOffset, length);
|
||||
fs.writeFileSync(path.join(__dirname, '/ColorNames.ts'), moduleData);
|
||||
console.log(`${moduleData.length} bytes written to ${path.join(__dirname, '/ColorNames.ts')}`);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,754 @@
|
||||
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
|
||||
255 250 250 snow
|
||||
248 248 255 ghost white
|
||||
248 248 255 GhostWhite
|
||||
245 245 245 white smoke
|
||||
245 245 245 WhiteSmoke
|
||||
220 220 220 gainsboro
|
||||
255 250 240 floral white
|
||||
255 250 240 FloralWhite
|
||||
253 245 230 old lace
|
||||
253 245 230 OldLace
|
||||
250 240 230 linen
|
||||
250 235 215 antique white
|
||||
250 235 215 AntiqueWhite
|
||||
255 239 213 papaya whip
|
||||
255 239 213 PapayaWhip
|
||||
255 235 205 blanched almond
|
||||
255 235 205 BlanchedAlmond
|
||||
255 228 196 bisque
|
||||
255 218 185 peach puff
|
||||
255 218 185 PeachPuff
|
||||
255 222 173 navajo white
|
||||
255 222 173 NavajoWhite
|
||||
255 228 181 moccasin
|
||||
255 248 220 cornsilk
|
||||
255 255 240 ivory
|
||||
255 250 205 lemon chiffon
|
||||
255 250 205 LemonChiffon
|
||||
255 245 238 seashell
|
||||
240 255 240 honeydew
|
||||
245 255 250 mint cream
|
||||
245 255 250 MintCream
|
||||
240 255 255 azure
|
||||
240 248 255 alice blue
|
||||
240 248 255 AliceBlue
|
||||
230 230 250 lavender
|
||||
255 240 245 lavender blush
|
||||
255 240 245 LavenderBlush
|
||||
255 228 225 misty rose
|
||||
255 228 225 MistyRose
|
||||
255 255 255 white
|
||||
0 0 0 black
|
||||
47 79 79 dark slate gray
|
||||
47 79 79 DarkSlateGray
|
||||
47 79 79 dark slate grey
|
||||
47 79 79 DarkSlateGrey
|
||||
105 105 105 dim gray
|
||||
105 105 105 DimGray
|
||||
105 105 105 dim grey
|
||||
105 105 105 DimGrey
|
||||
112 128 144 slate gray
|
||||
112 128 144 SlateGray
|
||||
112 128 144 slate grey
|
||||
112 128 144 SlateGrey
|
||||
119 136 153 light slate gray
|
||||
119 136 153 LightSlateGray
|
||||
119 136 153 light slate grey
|
||||
119 136 153 LightSlateGrey
|
||||
190 190 190 gray
|
||||
190 190 190 grey
|
||||
211 211 211 light grey
|
||||
211 211 211 LightGrey
|
||||
211 211 211 light gray
|
||||
211 211 211 LightGray
|
||||
25 25 112 midnight blue
|
||||
25 25 112 MidnightBlue
|
||||
0 0 128 navy
|
||||
0 0 128 navy blue
|
||||
0 0 128 NavyBlue
|
||||
100 149 237 cornflower blue
|
||||
100 149 237 CornflowerBlue
|
||||
72 61 139 dark slate blue
|
||||
72 61 139 DarkSlateBlue
|
||||
106 90 205 slate blue
|
||||
106 90 205 SlateBlue
|
||||
123 104 238 medium slate blue
|
||||
123 104 238 MediumSlateBlue
|
||||
132 112 255 light slate blue
|
||||
132 112 255 LightSlateBlue
|
||||
0 0 205 medium blue
|
||||
0 0 205 MediumBlue
|
||||
65 105 225 royal blue
|
||||
65 105 225 RoyalBlue
|
||||
0 0 255 blue
|
||||
30 144 255 dodger blue
|
||||
30 144 255 DodgerBlue
|
||||
0 191 255 deep sky blue
|
||||
0 191 255 DeepSkyBlue
|
||||
135 206 235 sky blue
|
||||
135 206 235 SkyBlue
|
||||
135 206 250 light sky blue
|
||||
135 206 250 LightSkyBlue
|
||||
70 130 180 steel blue
|
||||
70 130 180 SteelBlue
|
||||
176 196 222 light steel blue
|
||||
176 196 222 LightSteelBlue
|
||||
173 216 230 light blue
|
||||
173 216 230 LightBlue
|
||||
176 224 230 powder blue
|
||||
176 224 230 PowderBlue
|
||||
175 238 238 pale turquoise
|
||||
175 238 238 PaleTurquoise
|
||||
0 206 209 dark turquoise
|
||||
0 206 209 DarkTurquoise
|
||||
72 209 204 medium turquoise
|
||||
72 209 204 MediumTurquoise
|
||||
64 224 208 turquoise
|
||||
0 255 255 cyan
|
||||
224 255 255 light cyan
|
||||
224 255 255 LightCyan
|
||||
95 158 160 cadet blue
|
||||
95 158 160 CadetBlue
|
||||
102 205 170 medium aquamarine
|
||||
102 205 170 MediumAquamarine
|
||||
127 255 212 aquamarine
|
||||
0 100 0 dark green
|
||||
0 100 0 DarkGreen
|
||||
85 107 47 dark olive green
|
||||
85 107 47 DarkOliveGreen
|
||||
143 188 143 dark sea green
|
||||
143 188 143 DarkSeaGreen
|
||||
46 139 87 sea green
|
||||
46 139 87 SeaGreen
|
||||
60 179 113 medium sea green
|
||||
60 179 113 MediumSeaGreen
|
||||
32 178 170 light sea green
|
||||
32 178 170 LightSeaGreen
|
||||
152 251 152 pale green
|
||||
152 251 152 PaleGreen
|
||||
0 255 127 spring green
|
||||
0 255 127 SpringGreen
|
||||
124 252 0 lawn green
|
||||
124 252 0 LawnGreen
|
||||
0 255 0 green
|
||||
127 255 0 chartreuse
|
||||
0 250 154 medium spring green
|
||||
0 250 154 MediumSpringGreen
|
||||
173 255 47 green yellow
|
||||
173 255 47 GreenYellow
|
||||
50 205 50 lime green
|
||||
50 205 50 LimeGreen
|
||||
154 205 50 yellow green
|
||||
154 205 50 YellowGreen
|
||||
34 139 34 forest green
|
||||
34 139 34 ForestGreen
|
||||
107 142 35 olive drab
|
||||
107 142 35 OliveDrab
|
||||
189 183 107 dark khaki
|
||||
189 183 107 DarkKhaki
|
||||
240 230 140 khaki
|
||||
238 232 170 pale goldenrod
|
||||
238 232 170 PaleGoldenrod
|
||||
250 250 210 light goldenrod yellow
|
||||
250 250 210 LightGoldenrodYellow
|
||||
255 255 224 light yellow
|
||||
255 255 224 LightYellow
|
||||
255 255 0 yellow
|
||||
255 215 0 gold
|
||||
238 221 130 light goldenrod
|
||||
238 221 130 LightGoldenrod
|
||||
218 165 32 goldenrod
|
||||
184 134 11 dark goldenrod
|
||||
184 134 11 DarkGoldenrod
|
||||
188 143 143 rosy brown
|
||||
188 143 143 RosyBrown
|
||||
205 92 92 indian red
|
||||
205 92 92 IndianRed
|
||||
139 69 19 saddle brown
|
||||
139 69 19 SaddleBrown
|
||||
160 82 45 sienna
|
||||
205 133 63 peru
|
||||
222 184 135 burlywood
|
||||
245 245 220 beige
|
||||
245 222 179 wheat
|
||||
244 164 96 sandy brown
|
||||
244 164 96 SandyBrown
|
||||
210 180 140 tan
|
||||
210 105 30 chocolate
|
||||
178 34 34 firebrick
|
||||
165 42 42 brown
|
||||
233 150 122 dark salmon
|
||||
233 150 122 DarkSalmon
|
||||
250 128 114 salmon
|
||||
255 160 122 light salmon
|
||||
255 160 122 LightSalmon
|
||||
255 165 0 orange
|
||||
255 140 0 dark orange
|
||||
255 140 0 DarkOrange
|
||||
255 127 80 coral
|
||||
240 128 128 light coral
|
||||
240 128 128 LightCoral
|
||||
255 99 71 tomato
|
||||
255 69 0 orange red
|
||||
255 69 0 OrangeRed
|
||||
255 0 0 red
|
||||
255 105 180 hot pink
|
||||
255 105 180 HotPink
|
||||
255 20 147 deep pink
|
||||
255 20 147 DeepPink
|
||||
255 192 203 pink
|
||||
255 182 193 light pink
|
||||
255 182 193 LightPink
|
||||
219 112 147 pale violet red
|
||||
219 112 147 PaleVioletRed
|
||||
176 48 96 maroon
|
||||
199 21 133 medium violet red
|
||||
199 21 133 MediumVioletRed
|
||||
208 32 144 violet red
|
||||
208 32 144 VioletRed
|
||||
255 0 255 magenta
|
||||
238 130 238 violet
|
||||
221 160 221 plum
|
||||
218 112 214 orchid
|
||||
186 85 211 medium orchid
|
||||
186 85 211 MediumOrchid
|
||||
153 50 204 dark orchid
|
||||
153 50 204 DarkOrchid
|
||||
148 0 211 dark violet
|
||||
148 0 211 DarkViolet
|
||||
138 43 226 blue violet
|
||||
138 43 226 BlueViolet
|
||||
160 32 240 purple
|
||||
147 112 219 medium purple
|
||||
147 112 219 MediumPurple
|
||||
216 191 216 thistle
|
||||
255 250 250 snow1
|
||||
238 233 233 snow2
|
||||
205 201 201 snow3
|
||||
139 137 137 snow4
|
||||
255 245 238 seashell1
|
||||
238 229 222 seashell2
|
||||
205 197 191 seashell3
|
||||
139 134 130 seashell4
|
||||
255 239 219 AntiqueWhite1
|
||||
238 223 204 AntiqueWhite2
|
||||
205 192 176 AntiqueWhite3
|
||||
139 131 120 AntiqueWhite4
|
||||
255 228 196 bisque1
|
||||
238 213 183 bisque2
|
||||
205 183 158 bisque3
|
||||
139 125 107 bisque4
|
||||
255 218 185 PeachPuff1
|
||||
238 203 173 PeachPuff2
|
||||
205 175 149 PeachPuff3
|
||||
139 119 101 PeachPuff4
|
||||
255 222 173 NavajoWhite1
|
||||
238 207 161 NavajoWhite2
|
||||
205 179 139 NavajoWhite3
|
||||
139 121 94 NavajoWhite4
|
||||
255 250 205 LemonChiffon1
|
||||
238 233 191 LemonChiffon2
|
||||
205 201 165 LemonChiffon3
|
||||
139 137 112 LemonChiffon4
|
||||
255 248 220 cornsilk1
|
||||
238 232 205 cornsilk2
|
||||
205 200 177 cornsilk3
|
||||
139 136 120 cornsilk4
|
||||
255 255 240 ivory1
|
||||
238 238 224 ivory2
|
||||
205 205 193 ivory3
|
||||
139 139 131 ivory4
|
||||
240 255 240 honeydew1
|
||||
224 238 224 honeydew2
|
||||
193 205 193 honeydew3
|
||||
131 139 131 honeydew4
|
||||
255 240 245 LavenderBlush1
|
||||
238 224 229 LavenderBlush2
|
||||
205 193 197 LavenderBlush3
|
||||
139 131 134 LavenderBlush4
|
||||
255 228 225 MistyRose1
|
||||
238 213 210 MistyRose2
|
||||
205 183 181 MistyRose3
|
||||
139 125 123 MistyRose4
|
||||
240 255 255 azure1
|
||||
224 238 238 azure2
|
||||
193 205 205 azure3
|
||||
131 139 139 azure4
|
||||
131 111 255 SlateBlue1
|
||||
122 103 238 SlateBlue2
|
||||
105 89 205 SlateBlue3
|
||||
71 60 139 SlateBlue4
|
||||
72 118 255 RoyalBlue1
|
||||
67 110 238 RoyalBlue2
|
||||
58 95 205 RoyalBlue3
|
||||
39 64 139 RoyalBlue4
|
||||
0 0 255 blue1
|
||||
0 0 238 blue2
|
||||
0 0 205 blue3
|
||||
0 0 139 blue4
|
||||
30 144 255 DodgerBlue1
|
||||
28 134 238 DodgerBlue2
|
||||
24 116 205 DodgerBlue3
|
||||
16 78 139 DodgerBlue4
|
||||
99 184 255 SteelBlue1
|
||||
92 172 238 SteelBlue2
|
||||
79 148 205 SteelBlue3
|
||||
54 100 139 SteelBlue4
|
||||
0 191 255 DeepSkyBlue1
|
||||
0 178 238 DeepSkyBlue2
|
||||
0 154 205 DeepSkyBlue3
|
||||
0 104 139 DeepSkyBlue4
|
||||
135 206 255 SkyBlue1
|
||||
126 192 238 SkyBlue2
|
||||
108 166 205 SkyBlue3
|
||||
74 112 139 SkyBlue4
|
||||
176 226 255 LightSkyBlue1
|
||||
164 211 238 LightSkyBlue2
|
||||
141 182 205 LightSkyBlue3
|
||||
96 123 139 LightSkyBlue4
|
||||
198 226 255 SlateGray1
|
||||
185 211 238 SlateGray2
|
||||
159 182 205 SlateGray3
|
||||
108 123 139 SlateGray4
|
||||
202 225 255 LightSteelBlue1
|
||||
188 210 238 LightSteelBlue2
|
||||
162 181 205 LightSteelBlue3
|
||||
110 123 139 LightSteelBlue4
|
||||
191 239 255 LightBlue1
|
||||
178 223 238 LightBlue2
|
||||
154 192 205 LightBlue3
|
||||
104 131 139 LightBlue4
|
||||
224 255 255 LightCyan1
|
||||
209 238 238 LightCyan2
|
||||
180 205 205 LightCyan3
|
||||
122 139 139 LightCyan4
|
||||
187 255 255 PaleTurquoise1
|
||||
174 238 238 PaleTurquoise2
|
||||
150 205 205 PaleTurquoise3
|
||||
102 139 139 PaleTurquoise4
|
||||
152 245 255 CadetBlue1
|
||||
142 229 238 CadetBlue2
|
||||
122 197 205 CadetBlue3
|
||||
83 134 139 CadetBlue4
|
||||
0 245 255 turquoise1
|
||||
0 229 238 turquoise2
|
||||
0 197 205 turquoise3
|
||||
0 134 139 turquoise4
|
||||
0 255 255 cyan1
|
||||
0 238 238 cyan2
|
||||
0 205 205 cyan3
|
||||
0 139 139 cyan4
|
||||
151 255 255 DarkSlateGray1
|
||||
141 238 238 DarkSlateGray2
|
||||
121 205 205 DarkSlateGray3
|
||||
82 139 139 DarkSlateGray4
|
||||
127 255 212 aquamarine1
|
||||
118 238 198 aquamarine2
|
||||
102 205 170 aquamarine3
|
||||
69 139 116 aquamarine4
|
||||
193 255 193 DarkSeaGreen1
|
||||
180 238 180 DarkSeaGreen2
|
||||
155 205 155 DarkSeaGreen3
|
||||
105 139 105 DarkSeaGreen4
|
||||
84 255 159 SeaGreen1
|
||||
78 238 148 SeaGreen2
|
||||
67 205 128 SeaGreen3
|
||||
46 139 87 SeaGreen4
|
||||
154 255 154 PaleGreen1
|
||||
144 238 144 PaleGreen2
|
||||
124 205 124 PaleGreen3
|
||||
84 139 84 PaleGreen4
|
||||
0 255 127 SpringGreen1
|
||||
0 238 118 SpringGreen2
|
||||
0 205 102 SpringGreen3
|
||||
0 139 69 SpringGreen4
|
||||
0 255 0 green1
|
||||
0 238 0 green2
|
||||
0 205 0 green3
|
||||
0 139 0 green4
|
||||
127 255 0 chartreuse1
|
||||
118 238 0 chartreuse2
|
||||
102 205 0 chartreuse3
|
||||
69 139 0 chartreuse4
|
||||
192 255 62 OliveDrab1
|
||||
179 238 58 OliveDrab2
|
||||
154 205 50 OliveDrab3
|
||||
105 139 34 OliveDrab4
|
||||
202 255 112 DarkOliveGreen1
|
||||
188 238 104 DarkOliveGreen2
|
||||
162 205 90 DarkOliveGreen3
|
||||
110 139 61 DarkOliveGreen4
|
||||
255 246 143 khaki1
|
||||
238 230 133 khaki2
|
||||
205 198 115 khaki3
|
||||
139 134 78 khaki4
|
||||
255 236 139 LightGoldenrod1
|
||||
238 220 130 LightGoldenrod2
|
||||
205 190 112 LightGoldenrod3
|
||||
139 129 76 LightGoldenrod4
|
||||
255 255 224 LightYellow1
|
||||
238 238 209 LightYellow2
|
||||
205 205 180 LightYellow3
|
||||
139 139 122 LightYellow4
|
||||
255 255 0 yellow1
|
||||
238 238 0 yellow2
|
||||
205 205 0 yellow3
|
||||
139 139 0 yellow4
|
||||
255 215 0 gold1
|
||||
238 201 0 gold2
|
||||
205 173 0 gold3
|
||||
139 117 0 gold4
|
||||
255 193 37 goldenrod1
|
||||
238 180 34 goldenrod2
|
||||
205 155 29 goldenrod3
|
||||
139 105 20 goldenrod4
|
||||
255 185 15 DarkGoldenrod1
|
||||
238 173 14 DarkGoldenrod2
|
||||
205 149 12 DarkGoldenrod3
|
||||
139 101 8 DarkGoldenrod4
|
||||
255 193 193 RosyBrown1
|
||||
238 180 180 RosyBrown2
|
||||
205 155 155 RosyBrown3
|
||||
139 105 105 RosyBrown4
|
||||
255 106 106 IndianRed1
|
||||
238 99 99 IndianRed2
|
||||
205 85 85 IndianRed3
|
||||
139 58 58 IndianRed4
|
||||
255 130 71 sienna1
|
||||
238 121 66 sienna2
|
||||
205 104 57 sienna3
|
||||
139 71 38 sienna4
|
||||
255 211 155 burlywood1
|
||||
238 197 145 burlywood2
|
||||
205 170 125 burlywood3
|
||||
139 115 85 burlywood4
|
||||
255 231 186 wheat1
|
||||
238 216 174 wheat2
|
||||
205 186 150 wheat3
|
||||
139 126 102 wheat4
|
||||
255 165 79 tan1
|
||||
238 154 73 tan2
|
||||
205 133 63 tan3
|
||||
139 90 43 tan4
|
||||
255 127 36 chocolate1
|
||||
238 118 33 chocolate2
|
||||
205 102 29 chocolate3
|
||||
139 69 19 chocolate4
|
||||
255 48 48 firebrick1
|
||||
238 44 44 firebrick2
|
||||
205 38 38 firebrick3
|
||||
139 26 26 firebrick4
|
||||
255 64 64 brown1
|
||||
238 59 59 brown2
|
||||
205 51 51 brown3
|
||||
139 35 35 brown4
|
||||
255 140 105 salmon1
|
||||
238 130 98 salmon2
|
||||
205 112 84 salmon3
|
||||
139 76 57 salmon4
|
||||
255 160 122 LightSalmon1
|
||||
238 149 114 LightSalmon2
|
||||
205 129 98 LightSalmon3
|
||||
139 87 66 LightSalmon4
|
||||
255 165 0 orange1
|
||||
238 154 0 orange2
|
||||
205 133 0 orange3
|
||||
139 90 0 orange4
|
||||
255 127 0 DarkOrange1
|
||||
238 118 0 DarkOrange2
|
||||
205 102 0 DarkOrange3
|
||||
139 69 0 DarkOrange4
|
||||
255 114 86 coral1
|
||||
238 106 80 coral2
|
||||
205 91 69 coral3
|
||||
139 62 47 coral4
|
||||
255 99 71 tomato1
|
||||
238 92 66 tomato2
|
||||
205 79 57 tomato3
|
||||
139 54 38 tomato4
|
||||
255 69 0 OrangeRed1
|
||||
238 64 0 OrangeRed2
|
||||
205 55 0 OrangeRed3
|
||||
139 37 0 OrangeRed4
|
||||
255 0 0 red1
|
||||
238 0 0 red2
|
||||
205 0 0 red3
|
||||
139 0 0 red4
|
||||
215 7 81 DebianRed
|
||||
255 20 147 DeepPink1
|
||||
238 18 137 DeepPink2
|
||||
205 16 118 DeepPink3
|
||||
139 10 80 DeepPink4
|
||||
255 110 180 HotPink1
|
||||
238 106 167 HotPink2
|
||||
205 96 144 HotPink3
|
||||
139 58 98 HotPink4
|
||||
255 181 197 pink1
|
||||
238 169 184 pink2
|
||||
205 145 158 pink3
|
||||
139 99 108 pink4
|
||||
255 174 185 LightPink1
|
||||
238 162 173 LightPink2
|
||||
205 140 149 LightPink3
|
||||
139 95 101 LightPink4
|
||||
255 130 171 PaleVioletRed1
|
||||
238 121 159 PaleVioletRed2
|
||||
205 104 137 PaleVioletRed3
|
||||
139 71 93 PaleVioletRed4
|
||||
255 52 179 maroon1
|
||||
238 48 167 maroon2
|
||||
205 41 144 maroon3
|
||||
139 28 98 maroon4
|
||||
255 62 150 VioletRed1
|
||||
238 58 140 VioletRed2
|
||||
205 50 120 VioletRed3
|
||||
139 34 82 VioletRed4
|
||||
255 0 255 magenta1
|
||||
238 0 238 magenta2
|
||||
205 0 205 magenta3
|
||||
139 0 139 magenta4
|
||||
255 131 250 orchid1
|
||||
238 122 233 orchid2
|
||||
205 105 201 orchid3
|
||||
139 71 137 orchid4
|
||||
255 187 255 plum1
|
||||
238 174 238 plum2
|
||||
205 150 205 plum3
|
||||
139 102 139 plum4
|
||||
224 102 255 MediumOrchid1
|
||||
209 95 238 MediumOrchid2
|
||||
180 82 205 MediumOrchid3
|
||||
122 55 139 MediumOrchid4
|
||||
191 62 255 DarkOrchid1
|
||||
178 58 238 DarkOrchid2
|
||||
154 50 205 DarkOrchid3
|
||||
104 34 139 DarkOrchid4
|
||||
155 48 255 purple1
|
||||
145 44 238 purple2
|
||||
125 38 205 purple3
|
||||
85 26 139 purple4
|
||||
171 130 255 MediumPurple1
|
||||
159 121 238 MediumPurple2
|
||||
137 104 205 MediumPurple3
|
||||
93 71 139 MediumPurple4
|
||||
255 225 255 thistle1
|
||||
238 210 238 thistle2
|
||||
205 181 205 thistle3
|
||||
139 123 139 thistle4
|
||||
0 0 0 gray0
|
||||
0 0 0 grey0
|
||||
3 3 3 gray1
|
||||
3 3 3 grey1
|
||||
5 5 5 gray2
|
||||
5 5 5 grey2
|
||||
8 8 8 gray3
|
||||
8 8 8 grey3
|
||||
10 10 10 gray4
|
||||
10 10 10 grey4
|
||||
13 13 13 gray5
|
||||
13 13 13 grey5
|
||||
15 15 15 gray6
|
||||
15 15 15 grey6
|
||||
18 18 18 gray7
|
||||
18 18 18 grey7
|
||||
20 20 20 gray8
|
||||
20 20 20 grey8
|
||||
23 23 23 gray9
|
||||
23 23 23 grey9
|
||||
26 26 26 gray10
|
||||
26 26 26 grey10
|
||||
28 28 28 gray11
|
||||
28 28 28 grey11
|
||||
31 31 31 gray12
|
||||
31 31 31 grey12
|
||||
33 33 33 gray13
|
||||
33 33 33 grey13
|
||||
36 36 36 gray14
|
||||
36 36 36 grey14
|
||||
38 38 38 gray15
|
||||
38 38 38 grey15
|
||||
41 41 41 gray16
|
||||
41 41 41 grey16
|
||||
43 43 43 gray17
|
||||
43 43 43 grey17
|
||||
46 46 46 gray18
|
||||
46 46 46 grey18
|
||||
48 48 48 gray19
|
||||
48 48 48 grey19
|
||||
51 51 51 gray20
|
||||
51 51 51 grey20
|
||||
54 54 54 gray21
|
||||
54 54 54 grey21
|
||||
56 56 56 gray22
|
||||
56 56 56 grey22
|
||||
59 59 59 gray23
|
||||
59 59 59 grey23
|
||||
61 61 61 gray24
|
||||
61 61 61 grey24
|
||||
64 64 64 gray25
|
||||
64 64 64 grey25
|
||||
66 66 66 gray26
|
||||
66 66 66 grey26
|
||||
69 69 69 gray27
|
||||
69 69 69 grey27
|
||||
71 71 71 gray28
|
||||
71 71 71 grey28
|
||||
74 74 74 gray29
|
||||
74 74 74 grey29
|
||||
77 77 77 gray30
|
||||
77 77 77 grey30
|
||||
79 79 79 gray31
|
||||
79 79 79 grey31
|
||||
82 82 82 gray32
|
||||
82 82 82 grey32
|
||||
84 84 84 gray33
|
||||
84 84 84 grey33
|
||||
87 87 87 gray34
|
||||
87 87 87 grey34
|
||||
89 89 89 gray35
|
||||
89 89 89 grey35
|
||||
92 92 92 gray36
|
||||
92 92 92 grey36
|
||||
94 94 94 gray37
|
||||
94 94 94 grey37
|
||||
97 97 97 gray38
|
||||
97 97 97 grey38
|
||||
99 99 99 gray39
|
||||
99 99 99 grey39
|
||||
102 102 102 gray40
|
||||
102 102 102 grey40
|
||||
105 105 105 gray41
|
||||
105 105 105 grey41
|
||||
107 107 107 gray42
|
||||
107 107 107 grey42
|
||||
110 110 110 gray43
|
||||
110 110 110 grey43
|
||||
112 112 112 gray44
|
||||
112 112 112 grey44
|
||||
115 115 115 gray45
|
||||
115 115 115 grey45
|
||||
117 117 117 gray46
|
||||
117 117 117 grey46
|
||||
120 120 120 gray47
|
||||
120 120 120 grey47
|
||||
122 122 122 gray48
|
||||
122 122 122 grey48
|
||||
125 125 125 gray49
|
||||
125 125 125 grey49
|
||||
127 127 127 gray50
|
||||
127 127 127 grey50
|
||||
130 130 130 gray51
|
||||
130 130 130 grey51
|
||||
133 133 133 gray52
|
||||
133 133 133 grey52
|
||||
135 135 135 gray53
|
||||
135 135 135 grey53
|
||||
138 138 138 gray54
|
||||
138 138 138 grey54
|
||||
140 140 140 gray55
|
||||
140 140 140 grey55
|
||||
143 143 143 gray56
|
||||
143 143 143 grey56
|
||||
145 145 145 gray57
|
||||
145 145 145 grey57
|
||||
148 148 148 gray58
|
||||
148 148 148 grey58
|
||||
150 150 150 gray59
|
||||
150 150 150 grey59
|
||||
153 153 153 gray60
|
||||
153 153 153 grey60
|
||||
156 156 156 gray61
|
||||
156 156 156 grey61
|
||||
158 158 158 gray62
|
||||
158 158 158 grey62
|
||||
161 161 161 gray63
|
||||
161 161 161 grey63
|
||||
163 163 163 gray64
|
||||
163 163 163 grey64
|
||||
166 166 166 gray65
|
||||
166 166 166 grey65
|
||||
168 168 168 gray66
|
||||
168 168 168 grey66
|
||||
171 171 171 gray67
|
||||
171 171 171 grey67
|
||||
173 173 173 gray68
|
||||
173 173 173 grey68
|
||||
176 176 176 gray69
|
||||
176 176 176 grey69
|
||||
179 179 179 gray70
|
||||
179 179 179 grey70
|
||||
181 181 181 gray71
|
||||
181 181 181 grey71
|
||||
184 184 184 gray72
|
||||
184 184 184 grey72
|
||||
186 186 186 gray73
|
||||
186 186 186 grey73
|
||||
189 189 189 gray74
|
||||
189 189 189 grey74
|
||||
191 191 191 gray75
|
||||
191 191 191 grey75
|
||||
194 194 194 gray76
|
||||
194 194 194 grey76
|
||||
196 196 196 gray77
|
||||
196 196 196 grey77
|
||||
199 199 199 gray78
|
||||
199 199 199 grey78
|
||||
201 201 201 gray79
|
||||
201 201 201 grey79
|
||||
204 204 204 gray80
|
||||
204 204 204 grey80
|
||||
207 207 207 gray81
|
||||
207 207 207 grey81
|
||||
209 209 209 gray82
|
||||
209 209 209 grey82
|
||||
212 212 212 gray83
|
||||
212 212 212 grey83
|
||||
214 214 214 gray84
|
||||
214 214 214 grey84
|
||||
217 217 217 gray85
|
||||
217 217 217 grey85
|
||||
219 219 219 gray86
|
||||
219 219 219 grey86
|
||||
222 222 222 gray87
|
||||
222 222 222 grey87
|
||||
224 224 224 gray88
|
||||
224 224 224 grey88
|
||||
227 227 227 gray89
|
||||
227 227 227 grey89
|
||||
229 229 229 gray90
|
||||
229 229 229 grey90
|
||||
232 232 232 gray91
|
||||
232 232 232 grey91
|
||||
235 235 235 gray92
|
||||
235 235 235 grey92
|
||||
237 237 237 gray93
|
||||
237 237 237 grey93
|
||||
240 240 240 gray94
|
||||
240 240 240 grey94
|
||||
242 242 242 gray95
|
||||
242 242 242 grey95
|
||||
245 245 245 gray96
|
||||
245 245 245 grey96
|
||||
247 247 247 gray97
|
||||
247 247 247 grey97
|
||||
250 250 250 gray98
|
||||
250 250 250 grey98
|
||||
252 252 252 gray99
|
||||
252 252 252 grey99
|
||||
255 255 255 gray100
|
||||
255 255 255 grey100
|
||||
169 169 169 dark grey
|
||||
169 169 169 DarkGrey
|
||||
169 169 169 dark gray
|
||||
169 169 169 DarkGray
|
||||
0 0 139 dark blue
|
||||
0 0 139 DarkBlue
|
||||
0 139 139 dark cyan
|
||||
0 139 139 DarkCyan
|
||||
139 0 139 dark magenta
|
||||
139 0 139 DarkMagenta
|
||||
139 0 0 dark red
|
||||
139 0 0 DarkRed
|
||||
144 238 144 light green
|
||||
144 238 144 LightGreen
|
||||
@@ -21,6 +21,7 @@ import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowSe
|
||||
import { OscHandler } from 'common/parser/OscParser';
|
||||
import { DcsHandler } from 'common/parser/DcsParser';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { getColorFromName } from 'common/data/ColorNames';
|
||||
|
||||
/**
|
||||
* Map collect to glevel. Used in `selectCharset`.
|
||||
@@ -2877,13 +2878,14 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* with float numbering are not supported.
|
||||
*/
|
||||
protected _parseColorSpec(data: string): [number, number, number] | void {
|
||||
if (!data) return;
|
||||
// also handle uppercases
|
||||
data = data.toLowerCase();
|
||||
if (data.indexOf('rgb:') === 0) {
|
||||
let low = data.toLowerCase();
|
||||
if (low.indexOf('rgb:') === 0) {
|
||||
// 'rgb:' specifier
|
||||
data = data.slice(4);
|
||||
low = low.slice(4);
|
||||
const rex = /^([\da-f]{1})\/([\da-f]{1})\/([\da-f]{1})$|^([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})$|^([\da-f]{3})\/([\da-f]{3})\/([\da-f]{3})$|^([\da-f]{4})\/([\da-f]{4})\/([\da-f]{4})$/;
|
||||
const m = rex.exec(data);
|
||||
const m = rex.exec(low);
|
||||
if (m) {
|
||||
const base = m[1] ? 15 : m[4] ? 255 : m[7] ? 4095 : 65535;
|
||||
return [
|
||||
@@ -2892,20 +2894,21 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
Math.round(parseInt(m[3] || m[6] || m[9] || m[12], 16) / base * 255)
|
||||
];
|
||||
}
|
||||
} else if (data.indexOf('#') === 0) {
|
||||
} else if (low.indexOf('#') === 0) {
|
||||
// '#' specifier
|
||||
data = data.slice(1);
|
||||
low = low.slice(1);
|
||||
const rex = /^[\da-f]+$/;
|
||||
if (rex.exec(data) && [3, 6, 9, 12].includes(data.length)) {
|
||||
const adv = data.length / 3;
|
||||
if (rex.exec(low) && [3, 6, 9, 12].includes(low.length)) {
|
||||
const adv = low.length / 3;
|
||||
const result: [number, number, number] = [0, 0, 0];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
const c = parseInt(data.slice(adv * i, adv * i + adv), 16);
|
||||
const c = parseInt(low.slice(adv * i, adv * i + adv), 16);
|
||||
result[i] = adv === 1 ? c << 4 : adv === 2 ? c : adv === 3 ? c >> 4 : c >> 8;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return getColorFromName(data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2021 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* This module enables X11 color name lookups with the help of a perfect hash function
|
||||
* to not penalize the package size too much.
|
||||
* saving: ~70% (from 17kB down to 5kB)
|
||||
*/
|
||||
|
||||
// Note: module and table data created with fixtures/x11-colornames/create_module.js
|
||||
const TABLE = 'AB!!!id!jsih!ZYigHp3AkceNiiImVihW3Uih?DFihrenihDEQiwgziieGJvAoMnsidOM3idOtQiciazAsFrtieFZyidKSgAx8odip818ieFiXieF97ic34eihOxpA4UPNidz51A8znjBAX?uBU9ynitOZdigRMNBYgIEBcaXPBk9LVB0xlOB9mcFihmlWCRq0yidmG7idqsHid7RmCV7pCClqRAimG5kCpsb4ipt78CtqLeig17aigJb7ioC4rihzLdigmoNigEDTihzZKCwIz1C4j5sih4QQihlg2igwsHDBFTuDESshDJFzIig1cbihZ3wipZphigiKcihZUxihZLODRm7RilG1Cid3tmDVGffDYJsPDc1JrixgxGidDn3Dli9uDsOl0imDQPiyDhbimDyZihU00icbZSEJs6VieEzpicF2YEqB?PicemNiduxiihEL9ieBjnEuI53icdLPiqBYWiduYFExunsFB3JqFEXPuihnyvFQkNAFVVjlic8SLicIeOFYvurFwrh5icQ4RicHUgidVbJidVA3idN3LGECqgGJiKSGRl8UidT9qipssVGZHNyidy3widTu8idgHsidgcgGdggRGkODXihH!8ilyhpihWj0ihWcailWHjGwO?OilD4BG888ZHJzmGHZtoyicqlkiwWfkicEbdHg3uEHtMkRH0TgkH5MBRIQE9VIUh5VIYeSyieFFgIlC6Qidvc5idv65icprGicNfhItjoJI4N3mJRFpIicLVGJgMY7J2GebKAPoGKyITuidFGWic2olicYLfLFuJDidnoticCc!icx2bieAcuLIv3UicoYuic594LRQ86LZc3NidcphicnOVic09yisjDiitRyFLc7NTicTaFicFbvic6jPLk3JtigqSiL1QJUjJQZpidQvJicUVVidYVsidNOjidNQfidNnLicyCAicHGeidY17icL3cL8DSKMcPzVMgc8dicEg6ig61OMwImmM06KXM6Hl!M96LNicQEbicUjBNAt2Aid4Hwix3w0Ndba5Nt5pqNwuVljBbJaicYjeigAxGN1b!LOEvTnisIIoORf1cOVV!TiczJbiddd5iddgpiclyxidfd8idfuEieACwid?zWih2rlOp2waid?r2OtUKQOxMyjihUpcigKWQO4y32PNAPFidAU6PZAhBPhjAni0PYUiceDridjwXPqEBxPsZ5Cicoi9icBWoieHXOP0B?9QF50CigWlyQJBkUQMs8nici3YQQ?MXidedxicjVCidhu9icqIFidhZjidhBQid0avicmIYQZLp!QdLBNQwFKyipSwfikPB5Q1SZKipSC1idL08Q44Vaic4tpikVWWQ9x5KikK4sig4Afit?bgihvhKRA?wsidxIfidGjgikw?ORRruoRYQWbRh2dkRk!EPRo!Vpig!taR92Glicf4gicxZGSCIB1jED6KSF0tyid0MUieEUnidLfYSRRoKSUk5sSczRfih06gSkpOgikVvGio5X1icp8Kio5NFik0sjix9EQSp8Pvide28icanaidyPpidekWSx71CTANkkicssXTE1nojEbGQTJp32ic?fFTcYU6icuDuicNCIT1B67T4DhEice8dihBd7ismVIUIRe3UVJeiUZBPEVNXn3idXcIj0jici5yT6VgGbJVlXA2idcRxicfAXicT4kicRjbVpnXZieEm?V4feMigLlzV95OGip4?git4nTWF3csicyWQWJGH2ikH?FWMo06ieCn5WSC2fieDOsWUm1Tidor2WZoaQidoCjicz5cWlxroicTKOW4dS9ido5CidnBwic0AWXJX4lXNdDaicS!nXkWPBXotnyYAgsNicrXhicnmHidHe0idHlLicaNvicG8Jida06YMOfFidTV!icY0YidDcrYRiXUYZivaigDO8ig8GPigGNwi88iCikuzkiharXicoAoihJPbihae9ihJmOihJ9xigV9UiwsMyidaEBichf!ic9ZEYk9oiigCARY9kLuidkWPidknpidk?aihh0likBkKZEJFsidjdfieJmgZIU5dieH47isgQIZNxb3ZQn7hidI6HZVIi0il9ZLix9nYih92!ihCeNZZClyZhISFi1IDjid6bQicwQvZl66Eid6riZoGjRicpYuieBC5ic5jfZwlrsicKATimA?cZ8ZO6icxGJieAt2iculVaA40zidYsAacin?aglNzalwMVi9d0mictfZascgqicbxMbABJ?ignSAjYM8?bIhNZigd1qig7eVieJNPbQq8pikKkaigVPligW!fjgR?5bWCHKidCM1bcrI5idppfidpRsi5P6TbkXgIbo2xucEAZdihvCiidPJXidPYxicAACcIXb9isr67cMtDzcgfiVctsKmc8khZigZjTilrC1ihpKGjQhh5dJr30igymSjKJehihMVeig3VrigwENipRc!idKnBdRRFodhKEOdxEc9idEnCidE8zic!9VidK1md18eZit!FHieGkhicJ8SieCXticlSNidbjridA7YeIdgneNtbMeVlKqeZlSZicbpmixtEVesAlzfU2dAfdwW?fsSYbf5w59gB1xOicMKxgN1q8icZbagZPjpidSoWid1Y0ic2JSid1Bhgo7qeidcLjilYKFiw6S2isa5Jgxwl9g00UbicSMohA73XhELGKhUQqNi8cGshgsaridfCIhkkePhtUeth0vCqileCnit5YaiE?plieHKPiJTPmiN7Kt';
|
||||
const COLORS = '??r6!Pj?!Pj?9fX19fX13Nzc??rw??rw?fXm?fXm!vDm!uvX!uvX?!?V?!?V?!vN?!vN?!TE?9q5?9q5?96t?96t?!S1??jc???w??rN??rN??Xu8P?w9f?69f?68P??8Pj?8Pj?5ub6??D1??D1?!Th?!Th????AAAAL09PL09PL09PL09PaWlpaWlpaWlpaWlpcICQcICQcICQcICQd4iZd4iZd4iZd4iZvr6!vr6!09PT09PT09PT09PTGRlwGRlwAACAAACAAACAZJXtZJXtSD2LSD2LalrNalrNe2jue2juhHD?hHD?AADNAADNQWnhQWnhAAD?HpD?HpD?AL??AL??h87rh87rh876h876RoK0RoK0sMTesMTerdjmrdjmsODmsODmr!7ur!7uAM7RAM7RSNHMSNHMQODQAP??4P??4P??X56gX56gZs2qZs2qf??UAGQAAGQAVWsvVWsvj7yPj7yPLotXLotXPLNxPLNxILKqILKqmPuYmPuYAP9?AP9?fPwAfPwAAP8Af?8AAPqaAPqarf8vrf8vMs0yMs0yms0yms0yIosiIosia44ja44jvbdrvbdr8OaM7uiq7uiq!vrS!vrS???g???g??8A?9cA7t2C7t2C2qUguIYLuIYLvI!PvI!PzVxczVxci0UTi0UToFItzYU?3riH9fXc9d6z9KRg9KRg0rSM0mkesiIipSoq6ZZ66ZZ6!oBy?6B6?6B6?6UA?4wA?4wA?39Q8ICA8ICA?2NH?0UA?0UA?wAA?2m0?2m0?xST?xST?8DL?7bB?7bB23CT23CTsDBgxxWFxxWF0CCQ0CCQ?wD?7oLu3aDd2nDWulXTulXTmTLMmTLMlADTlADTiiviiivioCDwk3Dbk3Db2L?Y??r67unpzcnJi4mJ??Xu7uXezcW?i4aC?!?b7t?MzcCwi4N4?!TE7tW3zbeei31r?9q57sutza!Vi3dl?96t7s!hzbOLi3le??rN7um?zcmli4lw??jc7ujNzcixi4h4???w7u7gzc3Bi4uD8P?w4O7gwc3Bg4uD??D17uDlzcHFi4OG?!Th7tXSzbe1i3178P??4O7uwc3Ng4uLg2??emfuaVnNRzyLSHb?Q27uOl?NJ0CLAAD?AADuAADNAACLHpD?HIbuGHTNEE6LY7j?XKzuT5TNNmSLAL??ALLuAJrNAGiLh87?fsDubKbNSnCLsOL?pNPujbbNYHuLxuL?udPun7bNbHuLyuH?vNLuorXNbnuLv!??st?umsDNaIOL4P??0e7utM3NeouLu???ru7uls3NZouLmPX?juXuesXNU4aLAPX?AOXuAMXNAIaLAP??AO7uAM3NAIuLl???je7uec3NUouLf??Udu7GZs2qRYt0wf?BtO60m82baYtpVP!fTu6UQ82ALotXmv!akO6QfM18VItUAP9?AO52AM1mAItFAP8AAO4AAM0AAIsAf?8Adu4AZs0ARYsAwP8!s!46ms0yaYsiyv9wvO5oos1abos9??aP7uaFzcZzi4ZO?!yL7tyCzb5wi4FM???g7u7Rzc20i4t6??8A7u4Azc0Ai4sA?9cA7skAza0Ai3UA?8El7rQizZsdi2kU?7kP7q0OzZUMi2UI?8HB7rS0zZubi2lp?2pq7mNjzVVVizo6?4JH7nlCzWg5i0cm?9Ob7sWRzap9i3NV?!e67tiuzbqWi35m?6VP7ppJzYU?i1or?38k7nYhzWYdi0UT?zAw7iwszSYmixoa?0BA7js7zTMziyMj?4xp7oJizXBUi0w5?6B67pVyzYFii1dC?6UA7poAzYUAi1oA?38A7nYAzWYAi0UA?3JW7mpQzVtFiz4v?2NH7lxCzU85izYm?0UA7kAAzTcAiyUA?wAA7gAAzQAAiwAA1wdR?xST7hKJzRB2iwpQ?2607mqnzWCQizpi?7XF7qm4zZGei2Ns?6657qKtzYyVi19l?4Kr7nmfzWiJi0dd?zSz7jCnzSmQixxi?z6W7jqMzTJ4iyJS?wD?7gDuzQDNiwCL?4P67nrpzWnJi0eJ?7v?7q7uzZbNi2aL4Gb?0V?utFLNejeLvz7?sjrumjLNaCKLmzD?kSzufSbNVRqLq4L?n3nuiWjNXUeL?!H?7tLuzbXNi3uLqampqampqampqampAACLAACLAIuLAIuLiwCLiwCLiwAAiwAAkO6QkO6Q';
|
||||
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!?';
|
||||
const OFFSET = 551;
|
||||
const LENGTH = 551;
|
||||
const BUCKET_LENGTH = TABLE.length / LENGTH;
|
||||
|
||||
// match greyXX|grayXX names
|
||||
const rexGrey = /^gr[ae]y(\d+)/;
|
||||
// name match
|
||||
const rexName = /^\w?[A-Za-z0-9 ]+\w/;
|
||||
|
||||
function gray(n: number): [number, number, number] | undefined {
|
||||
if (0 <= n && n <= 100) {
|
||||
const v = Math.floor((n * 256 - n + 50) / 100);
|
||||
return [v, v, v];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function hash(d: number, name: string): number {
|
||||
if (!d) d = 0x01000193;
|
||||
for (const c of name) {
|
||||
d = ((d * 0x01000193) ^ c.charCodeAt(0)) & 0xffffffff;
|
||||
}
|
||||
return d >>> 0;
|
||||
}
|
||||
|
||||
function crc10(name: string, crc?: number): number {
|
||||
if (!crc) crc = 0;
|
||||
for (const c of name) {
|
||||
crc ^= c.charCodeAt(0) << 2;
|
||||
for (let k = 0; k < 8; k++) {
|
||||
crc = crc & 0x200 ? (crc << 1) ^ 0x233 : crc << 1;
|
||||
}
|
||||
}
|
||||
crc &= 0x3ff;
|
||||
return crc >>> 0;
|
||||
}
|
||||
|
||||
function loadData(idx: number): [number, number, number] {
|
||||
let value = 0;
|
||||
for (let i = idx * BUCKET_LENGTH; i < idx * BUCKET_LENGTH + BUCKET_LENGTH; ++i) {
|
||||
value *= ALPHABET.length;
|
||||
value += ALPHABET.indexOf(TABLE[i]);
|
||||
}
|
||||
return [value >>> 20, (value >> 10) & 0x3FF, value & 0x3FF];
|
||||
}
|
||||
|
||||
function loadColor(idx: number): [number, number, number] {
|
||||
// color buckets are hardcoded to 4 chars
|
||||
let v = 0;
|
||||
for (let i = idx * 4; i < idx * 4 + 4; ++i) {
|
||||
v *= ALPHABET.length;
|
||||
v += ALPHABET.indexOf(COLORS[i]);
|
||||
}
|
||||
return [v >>> 16, (v >> 8) & 0xFF, v & 0xFF];
|
||||
}
|
||||
|
||||
function lookupIdx(name: string): number {
|
||||
let b = loadData(hash(0, name) % LENGTH);
|
||||
b = loadData(b[0] < OFFSET ? (-(b[0] - OFFSET) - 1) : hash(b[0] - OFFSET, name) % LENGTH);
|
||||
const [ , , crc] = loadData(b[1]);
|
||||
return crc10(name) === crc ? b[1] : -1;
|
||||
}
|
||||
|
||||
export function getColorFromName(name: string): [number, number, number] | undefined {
|
||||
// basic name filtering
|
||||
if (name.length < 3 || name.length > 22 || !rexName.exec(name)) return;
|
||||
|
||||
// handle grays special
|
||||
const m = rexGrey.exec(name);
|
||||
if (m) return gray(parseInt(m[1]));
|
||||
|
||||
// grab crc checked idx from PHF
|
||||
const idx = lookupIdx(name);
|
||||
if (idx === -1) return;
|
||||
return loadColor(idx);
|
||||
}
|
||||
Reference in New Issue
Block a user