/*
    Color utilities.

    Copyright (C) 2005 Robert Lipe, robertlipe@usa.net

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA

 */

#include "defs.h"

/*
 * Colors derived from http://www.w3.org/TR/SVG/types.html#ColorKeywords
 * which is also referenced in the CSS3 spec from w3.org as being the
 * same colors supported by X11.
 */

static const struct {
  const char *cn;
  unsigned char r;
  unsigned char g;
  unsigned char b;
} color_table[] = {
  {"aliceblue", 240, 248, 255},
  {"antiquewhite", 250, 235, 215},
  {"aqua",  0, 255, 255},
  {"aquamarine", 127, 255, 212},
  {"azure", 240, 255, 255},
  {"beige", 245, 245, 220},
  {"bisque", 255, 228, 196},
  {"black",  0, 0, 0},
  {"blanchedalmond", 255, 235, 205},
  {"blue",  0, 0, 255},
  {"blueviolet", 138, 43, 226},
  {"brown", 165, 42, 42},
  {"burlywood", 222, 184, 135},
  {"cadetblue",  95, 158, 160},
  {"chartreuse", 127, 255, 0},
  {"chocolate", 210, 105, 30},
  {"coral", 255, 127, 80},
  {"cornflowerblue", 100, 149, 237},
  {"cornsilk", 255, 248, 220},
  {"crimson", 220, 20, 60},
  {"cyan",  0, 255, 255},
  {"darkblue",  0, 0, 139},
  {"darkcyan",  0, 139, 139},
  {"darkgoldenrod", 184, 134, 11},
  {"darkgray", 169, 169, 169},
  {"darkgreen",  0, 100, 0},
  {"darkgrey", 169, 169, 169},
  {"darkkhaki", 189, 183, 107},
  {"darkmagenta", 139, 0, 139},
  {"darkolivegreen",  85, 107, 47},
  {"darkorange", 255, 140, 0},
  {"darkorchid", 153, 50, 204},
  {"darkred", 139, 0, 0},
  {"darksalmon", 233, 150, 122},
  {"darkseagreen", 143, 188, 143},
  {"darkslateblue",  72, 61, 139},
  {"darkslategray",  47, 79, 79},
  {"darkslategrey",  47, 79, 79},
  {"darkturquoise",  0, 206, 209},
  {"darkviolet", 148, 0, 211},
  {"deeppink", 255, 20, 147},
  {"deepskyblue",  0, 191, 255},
  {"dimgray", 105, 105, 105},
  {"dimgrey", 105, 105, 105},
  {"dodgerblue",  30, 144, 255},
  {"firebrick", 178, 34, 34},
  {"floralwhite", 255, 250, 240},
  {"forestgreen",  34, 139, 34},
  {"fuchsia", 255, 0, 255},
  {"gainsboro", 220, 220, 220},
  {"ghostwhite", 248, 248, 255},
  {"gold", 255, 215, 0},
  {"goldenrod", 218, 165, 32},
  {"gray", 128, 128, 128},
  {"grey", 128, 128, 128},
  {"green",  0, 128, 0},
  {"greenyellow", 173, 255, 47},
  {"honeydew", 240, 255, 240},
  {"hotpink", 255, 105, 180},
  {"indianred", 205, 92, 92},
  {"indigo",  75, 0, 130},
  {"ivory", 255, 255, 240},
  {"khaki", 240, 230, 140},
  {"lavender", 230, 230, 250},
  {"lavenderblush", 255, 240, 245},
  {"lawngreen", 124, 252, 0},
  {"lemonchiffon", 255, 250, 205},
  {"lightblue", 173, 216, 230},
  {"lightcoral", 240, 128, 128},
  {"lightcyan", 224, 255, 255},
  {"lightgoldenrodyellow", 250, 250, 210},
  {"lightgray", 211, 211, 211},
  {"lightgreen", 144, 238, 144},
  {"lightgrey", 211, 211, 211},
  {"lightpink", 255, 182, 193},
  {"lightsalmon", 255, 160, 122},
  {"lightseagreen",  32, 178, 170},
  {"lightskyblue", 135, 206, 250},
  {"lightslategray", 119, 136, 153},
  {"lightslategrey", 119, 136, 153},
  {"lightsteelblue", 176, 196, 222},
  {"lightyellow", 255, 255, 224},
  {"lime",  0, 255, 0},
  {"limegreen",  50, 205, 50},
  {"linen", 250, 240, 230},
  {"magenta", 255, 0, 255},
  {"maroon", 128, 0, 0},
  {"mediumaquamarine", 102, 205, 170},
  {"mediumblue",  0, 0, 205},
  {"mediumorchid", 186, 85, 211},
  {"mediumpurple", 147, 112, 219},
  {"mediumseagreen",  60, 179, 113},
  {"mediumslateblue", 123, 104, 238},
  {"mediumspringgreen",  0, 250, 154},
  {"mediumturquoise",  72, 209, 204},
  {"mediumvioletred", 199, 21, 133},
  {"midnightblue",  25, 25, 112},
  {"mintcream", 245, 255, 250},
  {"mistyrose", 255, 228, 225},
  {"moccasin", 255, 228, 181},
  {"navajowhite", 255, 222, 173},
  {"navy",  0, 0, 128},
  {"oldlace", 253, 245, 230},
  {"olive", 128, 128, 0},
  {"olivedrab", 107, 142, 35},
  {"orange", 255, 165, 0},
  {"orangered", 255, 69, 0},
  {"orchid", 218, 112, 214},
  {"palegoldenrod", 238, 232, 170},
  {"palegreen", 152, 251, 152},
  {"paleturquoise", 175, 238, 238},
  {"palevioletred", 219, 112, 147},
  {"papayawhip", 255, 239, 213},
  {"peachpuff", 255, 218, 185},
  {"peru", 205, 133, 63},
  {"pink", 255, 192, 203},
  {"plum", 221, 160, 221},
  {"powderblue", 176, 224, 230},
  {"purple", 128, 0, 128},
  {"red", 255, 0, 0},
  {"rosybrown", 188, 143, 143},
  {"royalblue",  65, 105, 225},
  {"saddlebrown", 139, 69, 19},
  {"salmon", 250, 128, 114},
  {"sandybrown", 244, 164, 96},
  {"seagreen",  46, 139, 87},
  {"seashell", 255, 245, 238},
  {"sienna", 160, 82, 45},
  {"silver", 192, 192, 192},
  {"skyblue", 135, 206, 235},
  {"slateblue", 106, 90, 205},
  {"slategray", 112, 128, 144},
  {"slategrey", 112, 128, 144},
  {"snow", 255, 250, 250},
  {"springgreen",  0, 255, 127},
  {"steelblue",  70, 130, 180},
  {"tan", 210, 180, 140},
  {"teal",  0, 128, 128},
  {"thistle", 216, 191, 216},
  {"tomato", 255, 99, 71},
  {"turquoise",  64, 224, 208},
  {"violet", 238, 130, 238},
  {"wheat", 245, 222, 179},
  {"white", 255, 255, 255},
  {"whitesmoke", 245, 245, 245},
  {"yellow", 255, 255, 0},
  {"yellowgreen", 154, 205, 50},
};


/*
 * Functions for converting human-readable colors to BBGGRR value.
 * Substantial optimization opportunities remain.
 */
static int HexDigit(char hex)
{
  const char *Digits = "0123456789ABCDEF";
  const char *digits = "0123456789abcdef";
  char * ofs = strchr(digits, hex);
  if (ofs) {
    return ofs-digits;
  }

  ofs = strchr(Digits, hex);
  if (ofs) {
    return ofs-Digits;
  }
  return 0;
}

static int HexByte(const char* hex)
{
  int b = (HexDigit(hex[0])<<4)+HexDigit(hex[1]);
  return b;
}

/*
 * Given an input of the form:
 *   #<hex number for RGB value>
 *   <decimal nummber for BBGGRR value>
 *   <color named in CSS1 spec>
 * return the BBGGRR value for it.
 */

int
color_to_bbggrr(const char *opt_color)
{
  int color_num;
  unsigned int i;
  char *ep;

  color_num = strtol(opt_color, &ep, 10);

  if (ep != opt_color) {
    return color_num;
  }

  if (opt_color[0] == '#') {
    color_num = (HexByte(opt_color+1)) +      // red
                (HexByte(opt_color+3)<<8) +   // green
                (HexByte(opt_color+5)<<16);   // blue
    return color_num;
  }

  for (i = 0; i < sizeof(color_table) / sizeof(color_table[0]); i++) {
    if (0 == case_ignore_strcmp(opt_color, color_table[i].cn)) {
      return (color_table[i].b << 16) +
             (color_table[i].g << 8) +
             color_table[i].r;
    }
  }

  fatal("unrecognized color name %s\n", opt_color);
  return -1;
}
