Annotation of embedaddon/tmux/colour.c, revision 1.1

1.1     ! misho       1: /* $OpenBSD$ */
        !             2: 
        !             3: /*
        !             4:  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
        !             5:  * Copyright (c) 2016 Avi Halachmi <avihpit@yahoo.com>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
        !            16:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
        !            17:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19: 
        !            20: #include <sys/types.h>
        !            21: 
        !            22: #include <ctype.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: 
        !            26: #include "tmux.h"
        !            27: 
        !            28: static int
        !            29: colour_dist_sq(int R, int G, int B, int r, int g, int b)
        !            30: {
        !            31:        return ((R - r) * (R - r) + (G - g) * (G - g) + (B - b) * (B - b));
        !            32: }
        !            33: 
        !            34: static int
        !            35: colour_to_6cube(int v)
        !            36: {
        !            37:        if (v < 48)
        !            38:                return (0);
        !            39:        if (v < 114)
        !            40:                return (1);
        !            41:        return ((v - 35) / 40);
        !            42: }
        !            43: 
        !            44: /*
        !            45:  * Convert an RGB triplet to the xterm(1) 256 colour palette.
        !            46:  *
        !            47:  * xterm provides a 6x6x6 colour cube (16 - 231) and 24 greys (232 - 255). We
        !            48:  * map our RGB colour to the closest in the cube, also work out the closest
        !            49:  * grey, and use the nearest of the two.
        !            50:  *
        !            51:  * Note that the xterm has much lower resolution for darker colours (they are
        !            52:  * not evenly spread out), so our 6 levels are not evenly spread: 0x0, 0x5f
        !            53:  * (95), 0x87 (135), 0xaf (175), 0xd7 (215) and 0xff (255). Greys are more
        !            54:  * evenly spread (8, 18, 28 ... 238).
        !            55:  */
        !            56: int
        !            57: colour_find_rgb(u_char r, u_char g, u_char b)
        !            58: {
        !            59:        static const int        q2c[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
        !            60:        int                     qr, qg, qb, cr, cg, cb, d, idx;
        !            61:        int                     grey_avg, grey_idx, grey;
        !            62: 
        !            63:        /* Map RGB to 6x6x6 cube. */
        !            64:        qr = colour_to_6cube(r); cr = q2c[qr];
        !            65:        qg = colour_to_6cube(g); cg = q2c[qg];
        !            66:        qb = colour_to_6cube(b); cb = q2c[qb];
        !            67: 
        !            68:        /* If we have hit the colour exactly, return early. */
        !            69:        if (cr == r && cg == g && cb == b)
        !            70:                return ((16 + (36 * qr) + (6 * qg) + qb) | COLOUR_FLAG_256);
        !            71: 
        !            72:        /* Work out the closest grey (average of RGB). */
        !            73:        grey_avg = (r + g + b) / 3;
        !            74:        if (grey_avg > 238)
        !            75:                grey_idx = 23;
        !            76:        else
        !            77:                grey_idx = (grey_avg - 3) / 10;
        !            78:        grey = 8 + (10 * grey_idx);
        !            79: 
        !            80:        /* Is grey or 6x6x6 colour closest? */
        !            81:        d = colour_dist_sq(cr, cg, cb, r, g, b);
        !            82:        if (colour_dist_sq(grey, grey, grey, r, g, b) < d)
        !            83:                idx = 232 + grey_idx;
        !            84:        else
        !            85:                idx = 16 + (36 * qr) + (6 * qg) + qb;
        !            86:        return (idx | COLOUR_FLAG_256);
        !            87: }
        !            88: 
        !            89: /* Join RGB into a colour. */
        !            90: int
        !            91: colour_join_rgb(u_char r, u_char g, u_char b)
        !            92: {
        !            93:        return ((((int)((r) & 0xff)) << 16) |
        !            94:            (((int)((g) & 0xff)) << 8) |
        !            95:            (((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
        !            96: }
        !            97: 
        !            98: /* Split colour into RGB. */
        !            99: void
        !           100: colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
        !           101: {
        !           102:        *r = (c >> 16) & 0xff;
        !           103:        *g = (c >> 8) & 0xff;
        !           104:        *b = c & 0xff;
        !           105: }
        !           106: 
        !           107: /* Convert colour to a string. */
        !           108: const char *
        !           109: colour_tostring(int c)
        !           110: {
        !           111:        static char     s[32];
        !           112:        u_char          r, g, b;
        !           113: 
        !           114:        if (c & COLOUR_FLAG_RGB) {
        !           115:                colour_split_rgb(c, &r, &g, &b);
        !           116:                xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
        !           117:                return (s);
        !           118:        }
        !           119: 
        !           120:        if (c & COLOUR_FLAG_256) {
        !           121:                xsnprintf(s, sizeof s, "colour%u", c & 0xff);
        !           122:                return (s);
        !           123:        }
        !           124: 
        !           125:        switch (c) {
        !           126:        case 0:
        !           127:                return ("black");
        !           128:        case 1:
        !           129:                return ("red");
        !           130:        case 2:
        !           131:                return ("green");
        !           132:        case 3:
        !           133:                return ("yellow");
        !           134:        case 4:
        !           135:                return ("blue");
        !           136:        case 5:
        !           137:                return ("magenta");
        !           138:        case 6:
        !           139:                return ("cyan");
        !           140:        case 7:
        !           141:                return ("white");
        !           142:        case 8:
        !           143:                return ("default");
        !           144:        case 90:
        !           145:                return ("brightblack");
        !           146:        case 91:
        !           147:                return ("brightred");
        !           148:        case 92:
        !           149:                return ("brightgreen");
        !           150:        case 93:
        !           151:                return ("brightyellow");
        !           152:        case 94:
        !           153:                return ("brightblue");
        !           154:        case 95:
        !           155:                return ("brightmagenta");
        !           156:        case 96:
        !           157:                return ("brightcyan");
        !           158:        case 97:
        !           159:                return ("brightwhite");
        !           160:        }
        !           161:        return (NULL);
        !           162: }
        !           163: 
        !           164: /* Convert colour from string. */
        !           165: int
        !           166: colour_fromstring(const char *s)
        !           167: {
        !           168:        const char      *errstr;
        !           169:        const char      *cp;
        !           170:        int              n;
        !           171:        u_char           r, g, b;
        !           172: 
        !           173:        if (*s == '#' && strlen(s) == 7) {
        !           174:                for (cp = s + 1; isxdigit((u_char) *cp); cp++)
        !           175:                        ;
        !           176:                if (*cp != '\0')
        !           177:                        return (-1);
        !           178:                n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
        !           179:                if (n != 3)
        !           180:                        return (-1);
        !           181:                return (colour_join_rgb(r, g, b));
        !           182:        }
        !           183: 
        !           184:        if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
        !           185:                n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
        !           186:                if (errstr != NULL)
        !           187:                        return (-1);
        !           188:                return (n | COLOUR_FLAG_256);
        !           189:        }
        !           190: 
        !           191:        if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
        !           192:                return (0);
        !           193:        if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
        !           194:                return (1);
        !           195:        if (strcasecmp(s, "green") == 0 || strcmp(s, "2") == 0)
        !           196:                return (2);
        !           197:        if (strcasecmp(s, "yellow") == 0 || strcmp(s, "3") == 0)
        !           198:                return (3);
        !           199:        if (strcasecmp(s, "blue") == 0 || strcmp(s, "4") == 0)
        !           200:                return (4);
        !           201:        if (strcasecmp(s, "magenta") == 0 || strcmp(s, "5") == 0)
        !           202:                return (5);
        !           203:        if (strcasecmp(s, "cyan") == 0 || strcmp(s, "6") == 0)
        !           204:                return (6);
        !           205:        if (strcasecmp(s, "white") == 0 || strcmp(s, "7") == 0)
        !           206:                return (7);
        !           207:        if (strcasecmp(s, "default") == 0 || strcmp(s, "8") == 0)
        !           208:                return (8);
        !           209:        if (strcasecmp(s, "brightblack") == 0 || strcmp(s, "90") == 0)
        !           210:                return (90);
        !           211:        if (strcasecmp(s, "brightred") == 0 || strcmp(s, "91") == 0)
        !           212:                return (91);
        !           213:        if (strcasecmp(s, "brightgreen") == 0 || strcmp(s, "92") == 0)
        !           214:                return (92);
        !           215:        if (strcasecmp(s, "brightyellow") == 0 || strcmp(s, "93") == 0)
        !           216:                return (93);
        !           217:        if (strcasecmp(s, "brightblue") == 0 || strcmp(s, "94") == 0)
        !           218:                return (94);
        !           219:        if (strcasecmp(s, "brightmagenta") == 0 || strcmp(s, "95") == 0)
        !           220:                return (95);
        !           221:        if (strcasecmp(s, "brightcyan") == 0 || strcmp(s, "96") == 0)
        !           222:                return (96);
        !           223:        if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
        !           224:                return (97);
        !           225:        return (-1);
        !           226: }
        !           227: 
        !           228: /* Convert 256 colour palette to 16. */
        !           229: u_char
        !           230: colour_256to16(u_char c)
        !           231: {
        !           232:        static const u_char table[256] = {
        !           233:                 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
        !           234:                 0,  4,  4,  4, 12, 12,  2,  6,  4,  4, 12, 12,  2,  2,  6,  4,
        !           235:                12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
        !           236:                10, 10, 10, 14,  1,  5,  4,  4, 12, 12,  3,  8,  4,  4, 12, 12,
        !           237:                 2,  2,  6,  4, 12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10,
        !           238:                14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  5,  4, 12, 12,  1,  1,
        !           239:                 5,  4, 12, 12,  3,  3,  8,  4, 12, 12,  2,  2,  2,  6, 12, 12,
        !           240:                10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  1,  5,
        !           241:                12, 12,  1,  1,  1,  5, 12, 12,  1,  1,  1,  5, 12, 12,  3,  3,
        !           242:                 3,  7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
        !           243:                 9,  9,  9,  9, 13, 12,  9,  9,  9,  9, 13, 12,  9,  9,  9,  9,
        !           244:                13, 12,  9,  9,  9,  9, 13, 12, 11, 11, 11, 11,  7, 12, 10, 10,
        !           245:                10, 10, 10, 14,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,
        !           246:                 9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,
        !           247:                 9, 13, 11, 11, 11, 11, 11, 15,  0,  0,  0,  0,  0,  0,  8,  8,
        !           248:                 8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15
        !           249:        };
        !           250: 
        !           251:        return (table[c]);
        !           252: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>