// -*- c++ -*-
/* $Id: color.ccg,v 1.4 2005/11/29 16:38:10 murrayc Exp $ */

/*
 *
 * Copyright 2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gdkmm/colormap.h>
#include <gdk/gdkcolor.h>
#include <gdk/gdkrgb.h>

namespace Gdk
{

Color::Color()
{
  GdkColor tmp = { 0, 0, 0, 0, };
  gobject_ = gdk_color_copy(&tmp);
}

Color::Color(const Glib::ustring& value)
{
  GdkColor tmp = { 0, 0, 0, 0, };
  gobject_ = gdk_color_copy(&tmp);

  set(value);
}

void Color::set_grey(gushort value)
{
  gobject_->red = gobject_->green = gobject_->blue = value;
}

void Color::set_grey_p(double g)
{
 gobject_->red = gobject_->green = gobject_->blue = (gushort)(g * 65535.0);
}

void Color::set_rgb(gushort red_, gushort green_, gushort blue_)
{
  gobject_->red = red_;
  gobject_->green = green_;
  gobject_->blue = blue_;
}

void Color::set_rgb_p(double red_, double green_, double blue_)
{
  gobject_->red = (gushort)(red_ * 65535.0);
  gobject_->green = (gushort)(green_ * 65535.0);
  gobject_->blue = (gushort)(blue_ * 65535.0);
}

void Color::set_hsv(double h, double s, double v)
{
  //TODO: Comments/Documentation. I have no idea what this code does. murrayc.
  
  h /= 60.0;
  int i = (int)h;
  double p = v * (1 - s);
  double q = v * (1 - s * (h - i));
  double t = v * (1 - s * (1 - h + i));

  switch(i)
  {
    case 0:
      set_rgb_p(v, t, p);
      break;
    case 1:
      set_rgb_p(q, v, p);
      break;
    case 2:
      set_rgb_p(p, v, t);
      break;
    case 3:
      set_rgb_p(p, q, v);
      break;
    case 4:
      set_rgb_p(t, p, v);
      break;
    default:
      set_rgb_p(v, p, q);
  }
}

void Color::set_hsl(double h, double s, double l)
{
  //TODO: Comments/Documentation. I have no idea what this code does. murrayc.

  if(s == 0.0)
    set_grey_p(l);
  else
  {
    double t2 = (l < 0.5) ? l * (1.0 + s) : l + s - l * s;
    double t1 = 2*l-t2;
    h /= 360.0;

    double tr = h + 1.0/3.0;
    double tg = h;
    double tb = h - 1.0/3.0;
    if (tb < 0) tb += 1.0;

    double r = 0.0, g = 0.0, b = 0.0;

    if (tr < 1.0/6.0)
      r = t1 +(t2-t1) * 6 * tr;
    else if (tr < 1.0/2.0)
      r = t2;
    else if (tr < 2.0/3.0)
      r = t1+(t2-t1)*(2.0/3.0 - tr) * 6.0;

    if (tg < 1.0/6.0)
      g = t1 + (t2 - t1) * 6 * tg;
    else if (tg < 1.0/2.0)
      g = t2;
    else if (tg < 2.0/3.0)
      g = t1+(t2-t1)*(2.0/3.0 - tg) * 6.0;

    if (tb < 1.0/6.0)
      b = t1 +(t2-t1) * 6 * tb;
    else if (tb < 1.0/2.0)
      b = t2;
    else if (tb < 2.0/3.0)
      b = t1+(t2-t1)*(2.0/3.0 - tb) * 6.0;

    set_rgb_p(r, g, b);
  }
}

bool Color::set(const Glib::ustring& value)
{
  return gdk_color_parse(value.c_str(), gobj());
}

_DEPRECATE_IFDEF_START
bool Color::parse(const Glib::ustring& spec)
{
  return set(spec);
}
_DEPRECATE_IFDEF_END

gushort Color::get_red() const
{
  return gobject_->red;
}

gushort Color::get_green() const
{
  return gobject_->green;

}
gushort Color::get_blue() const
{
 return gobject_->blue;
}

void Color::set_red(gushort value)
{
  gobject_->red = value;
}

void Color::set_green(gushort value)
{
  gobject_->green = value;
}

void Color::set_blue(gushort value)
{
  gobject_->blue = value;
}

void Color::rgb_find_color(const Glib::RefPtr<Gdk::Colormap>& map)
{
  gdk_rgb_find_color(map->gobj(), gobj());
}

guint Color::get_pixel() const
{
  return gobject_->pixel;
}

double Color::get_red_p() const
{
  return gobject_->red / 65535.0;
}

double Color::get_green_p() const
{
  return gobject_->green / 65535.0;
}

double Color::get_blue_p() const
{
  return gobject_->blue / 65535.0;
}


} //namespace Gdk

