/**
 * This file describes color attributes needed for rendering.
 * Classes described here are IColor.
 *
 *   IBM Open Class Library
 *   (C) Copyright International Business Machines Corporation,  1997
 *   Licensed Material - Program-Property of IBM - All Rights Reserved.
 */

// Revision: 26 1.11.4.12 source/albert/graph2d/ibcolor.hpp, 2d, ioc.v400, 980918 

#ifndef _IBCOLOR_
#define _IBCOLOR_

#include <ibase.hpp>
#include <imstrmbl.hpp>
#include <igraphpl.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class IColorProfile;
class IColor;
class IIndexColor;
class ISystemColor;

class IColorMap;

// used in most device color spaces range should be O <= GIntensity <= 1.0
typedef float GIntensity;

// used on Compact Color 0 <= CharIntensity <= 255
typedef unsigned char CharIntensity;

#pragma enum(4)
#pragma pack(push,4)

/**
 * IColor is a concrete class that encapsulates all possible color spaces including RGB, HSV, and CIE-XYZ.
 * It has the default representation of compact RGB color (each element of red, green, and blue is
 * represented by an 8-bit unsigned integer).
 */

class IBaseColor : public IMSTREAMABLE
{
	StreamableDeclarationsMacro(IBaseColor);

public:
	
	/** Definition of some commonly used colors for convience. */
	enum EPredefinedColor {
		kWhite=0,
		kBlue,
		kRed,
		kPink,
		kGreen,
		kCyan,
		kYellow,
		kBlack,
		kDarkGray,
		kDarkBlue,
		kDarkRed,
		kDarkPink,
		kDarkGreen,
		kDarkCyan,
		kBrown,
		kPaleGray
	};


	/**
	 * Constructs a default black color.
	 */
	IBaseColor();

	/**
	 * Constructs of a predefined commonly used color.
	 */
	IBaseColor(EPredefinedColor commonlyUsedColor);

	/**
	 * Constructs a gray color.
	 */
	IBaseColor(CharIntensity gray, CharIntensity opacity = 255);

	/**
	 * Copy constructor.
	 */
	IBaseColor(const IBaseColor&);

	/**
	 * Constructs the color from a compact RGB color.
	 */
	IBaseColor(
		CharIntensity red,
		CharIntensity green,
		CharIntensity blue,
		CharIntensity opacity = 255);

	virtual ~IBaseColor();
	
	/**
	 * Assignment operator.
	 */
	IBaseColor& operator=(const IBaseColor& source);

	/**
	 * Tests two IBaseColor objects for equality.
	 */
	virtual bool operator==(const IBaseColor&) const;

	/**
	 * Tests two IBaseColor objects for inequality.
	 */
	bool operator!=(const IBaseColor&) const;

	/**
	 * Returns the red component of the compact RGB color.
	 */
	virtual CharIntensity redMix() const;

	/**
	 * Returns the green component of the compact RGB color.
	 */
	virtual CharIntensity greenMix() const;

	/**
	 * Returns the blue component of the compact RGB color.
	 */
	virtual CharIntensity blueMix() const;

	/**
	 * Returns the opacity of the compact RGB color.
	 */
	virtual CharIntensity opacity() const;

	/**
	 * Returns the intensity of a gray color.
	 */
	virtual CharIntensity gray() const;

	/**
	 * Sets the red component of the compact RGB color.
	 */
	virtual IBaseColor& setRed(CharIntensity red);

	/**
	 * Sets the green component of the compact RGB color.
	 */
	virtual IBaseColor& setGreen(CharIntensity green);

	/**
	 * Sets the blue component of the compact RGB color.
	 */
	virtual IBaseColor& setBlue(CharIntensity blue);

	/**
	 * Sets the opacity of the compact RGB color.
	 */
	virtual IBaseColor& setOpacity(CharIntensity opacity);

	/**
	 * Converts a RGB color to XYZ color space.
	 */
	virtual void elementsInXYZColorSpace(
		GIntensity& x,
		GIntensity& y,
		GIntensity& z) const;

	/**
	 * Sets the color by converting an XYZ color to a compact RGB color.
	 */
	virtual void setElementsInXYZColorSpace(
		GIntensity x,
		GIntensity y,
		GIntensity z);

	/**
	 * Gets the red component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void redMix(GIntensity& red) const;

	/**
	 * Gets the green component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void greenMix(GIntensity& green) const;

	/**
	 * Gets the blue component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void blueMix(GIntensity& blue) const;

	/**
	 * Gets the opacity value of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void opacity(GIntensity& opacity) const;

protected:
	/** Stream out this object to the stream for polymorphic streaming
	 */
	virtual void writeToStream(IDataStream& toWhere) const;

	/** Stream in this object from the stream in for polymorphic streaming
	 */
	virtual void readFromStream(IDataStream& fromWhere);

	/** Copy RGBA values over from source color
	 */
	IBaseColor& copyRGBA(const IBaseColor& source);

	/** set RGBA values in a single call
	 */
	void setRGB(
		CharIntensity r,
		CharIntensity g,
		CharIntensity b,
		CharIntensity o = 255);

protected :

	//when no palette support is required then creating index from rgb values and vice-versa
  long createIndex( CharIntensity r,
                    CharIntensity g,
                    CharIntensity b);

  void rgbFromIndex(unsigned long index);

	CharIntensity fRed;
	CharIntensity fGreen;
	CharIntensity fBlue;
	CharIntensity fOpacity;

	const IColorProfile* colorProfile() const;
	static const IColorProfile* fgColorProfile;

#if (IC_OBSOLETE <= IC_OBSOLETE_3)      // ajd 2/8/1998
public:
	enum Color {
		white=0,
		blue,
		red,
		pink,
		green,
		cyan,
		yellow,
		black,
		darkGray,
		darkBlue,
		darkRed,
		darkPink,
		darkGreen,
		darkCyan,
		brown,
		paleGray
	};

	IBaseColor(Color color);
	
	virtual bool operator==(const IBaseColor::Color src) const;

#endif // IC_OBSOLETE
};

class IColor : public IBaseColor
{
public:
	enum ESystemColor {
		kShadowIconHiliteBgnd=0,
		kShadowIconHiliteFgnd,
		kShadowIconText,
		kEntryFieldBgnd,
		kListBoxBgnd,
		kDisableMenuText,
		kMenuHiliteText,
		kMenuHiliteBgnd,
		kNotebookPageBgnd,
		kInactiveScrollBar,
		kDefaultControl,
		kButtonLight,
		kButtonMiddle,
		kButtonDark,
		kDefaultButton,
		kTitleLine,
		kMenuShadow,
		kDialogShadow,
		kIconText,
		kDialogBgnd,
		kHiliteFgnd,
		kHiliteBgnd,
		kInactiveTitleTextBgnd,
		kActiveTitleTextBgnd,
		kInactiveTitleText,
		kActiveTitleText,
		kOutputText,
		kWindowStaticText,
		kScrollBar,
		kDesktopBgnd,
		kActiveTitleBgnd,
		kInactiveTitleBgnd,
		kMenuBgnd,
		kWindowBgnd,
		kFrameBorder,
		kMenuText,
		kWindowText,
		kTitleText,
		kSizeBar,
		kScrollArrow,
		kActiveFrameBorder,
		kInactiveFrameBorder,
		kMainWindowBgnd,
		kHelpWindowBgnd,
		kHelpText,
		kHelpHiliteText
#if (IC_OBSOLETE <= IC_OBSOLETE_3)
      ,
      shadowIconHiliteBgnd=0,
      shadowIconHiliteFgnd=1,
      shadowIconText=2,
      entryFieldBgnd=3,
      listBoxBgnd=4,
      disableMenuText=5,
      menuHiliteText=6,
      menuHiliteBgnd=7,
      notebookPageBgnd=8,
      inactiveScrollBar=9,
      defaultControl=10,
      buttonLight=11,
      buttonMiddle=12,
      buttonDark=13,
      defaultButton=14,
      titleLine=15,
      menuShadow=16,
      dialogShadow=17,
      iconText=18,
      dialogBgnd=19,
      hiliteFgnd=20,
      hiliteBgnd=21,
      inactiveTitleTextBgnd=22,
      activeTitleTextBgnd=23,
      inactiveTitleText=24,
      activeTitleText=25,
      outputText=26,
      windowStaticText=27,
      scrollBar=28,
      desktopBgnd=29,
      activeTitleBgnd=30,
      inactiveTitleBgnd=31,
      menuBgnd=32,
      windowBgnd=33,
      frameBorder=34,
      menuText=35,
      windowText=36,
      titleText=37,
      sizeBar=38,
      scrollArrow=39,
      activeFrameBorder=40,
      inactiveFrameBorder=41,
      mainWindowBgnd=42,
      helpWindowBgnd=43,
      helpText=44,
      helpHiliteText=45
#endif // IC_OBSOLETE
	};

#if (IC_OBSOLETE <= IC_OBSOLETE_3)
   typedef ESystemColor SystemColor;
#endif // IC_OBSOLETE

	/**
	 * Constructor for a system preset gui color, lazy evaluated RGBA values
	 */
	IColor(ESystemColor value);

	/**
	 * Constructor for a predefined RGBA color
	 */
	IColor(EPredefinedColor color);

	/**
	 * Constructs color from a compact RGBA color. It could be an index color optionally by passing in the colorMap
	 */
	//IColor(
	//	CharIntensity red,
	//	CharIntensity green,
	//	CharIntensity blue,
	//	CharIntensity opacity = 255,
	//	const IColorMap* referencedColorMap = 0 /*NIL*/);
	IColor(
		CharIntensity red,
		CharIntensity green,
		CharIntensity blue,
		CharIntensity opacity = 255);	// for the first cut, this assumes system default palette

	/** Constructor for index color associated with a color map (os/2 only: -2 == white, -1 == black)
	 */
	IColor(unsigned long index, const IColorMap* referencedColorMap=NULL);

	/**
	 * Copy constructor.
	 */
	IColor(const IColor& color);

	virtual ~IColor();

	/**
	 * Assignment operator.
	 */
	IColor& operator=(const IColor& color);

	/**
	 * Tests two IBaseColor objects for equality.
	 */
	virtual bool operator==(const IBaseColor& color) const;

	/**
	 * Getter for the system preset gui color enum
	 */
	ESystemColor runtimeGuiColor() const;

	/**
	 * Getter for the predefined color enum
	 */
	IBaseColor::EPredefinedColor predefinedColor() const;

	/**
	 * Getter for the native color representation in a long
	 */
	long asRGBLong() const;

	/**
	 * Getter for the color index
	 */
	// virtual long index(const IColorMap* colorMap = 0 /*NIL*/) const;

	// Index value for an IColor object created using index parameter and IColor object created using
	// r,g b values can be different. In the later case it tries to get the nearest index.

	virtual long index() const;	// for the first cut, this assumes system default palette

	/**
	 * Returns the red component of the compact RGB color.
	 */
	virtual CharIntensity redMix() const;

	/**
	 * Returns the green component of the compact RGB color.
	 */
	virtual CharIntensity greenMix() const;

	/**
	 * Returns the blue component of the compact RGB color.
	 */
	virtual CharIntensity blueMix() const;

	/**
	 * Returns the opacity of the compact RGB color.
	 */
	virtual CharIntensity opacity() const;

	/**
	 * Returns the intensity of a gray color.
	 */
	virtual CharIntensity gray() const;

	/**
	 * Gets the red component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void redMix(GIntensity& red) const;

	/**
	 * Gets the green component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void greenMix(GIntensity& green) const;

	/**
	 * Gets the blue component of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void blueMix(GIntensity& blue) const;

	/**
	 * Gets the opacity value of a floating-point RGB color by scaling into range of 0-1.
	 */
	virtual void opacity(GIntensity& opacity) const;

	/**
	 * Sets the red component of the compact RGB color.
	 */
	virtual IBaseColor& setRed(CharIntensity red);

	/**
	 * Sets the green component of the compact RGB color.
	 */
	virtual IBaseColor& setGreen(CharIntensity green);

	/**
	 * Sets the blue component of the compact RGB color.
	 */
	virtual IBaseColor& setBlue(CharIntensity blue);

	/**
	 * Sets the opacity of the compact RGB color.
	 */
	virtual IBaseColor& setOpacity(CharIntensity opacity);

	/**
	 * Converts a RGB color to XYZ color space.
	 */
	virtual void elementsInXYZColorSpace(
		GIntensity& x,
		GIntensity& y,
		GIntensity& z) const;

	/**
	 * Sets the color by converting an XYZ color to a index color. If the value of the color does not match any color in the color map, the closist color index will be used.
	 */
	virtual void setElementsInXYZColorSpace(GIntensity x, GIntensity y, GIntensity z);

protected:
	/** Stream out this object to the stream for polymorphic streaming
	 */
	virtual void writeToStream(IDataStream& toWhere) const;

	/** Stream in this object from the stream in for polymorphic streaming
	 */
	virtual void readFromStream(IDataStream& fromWhere);

protected:
	IColor();

private:
	IBaseColor& evaluate();	// for system color...

	IBaseColor& validate();	// type change
	
	static IBaseColor nativeSystemColor(IColor::ESystemColor systemColor);

	enum EColorType {
		kRGB=0,
		kPredefined,
		kSystem,
		kIndex
	};

	EColorType fType;
	long fValue;
	bool fValueCache;

#if (IC_OBSOLETE <= IC_OBSOLETE_3)
public:

	// use IColor(IColor::EPredefinedColor) instead
	IColor(Color color);

	virtual bool operator==(const IColor::Color src) const;

#ifdef IC_MOTIF
	// use IColor::index() instead.
	virtual unsigned long asPixel() const;
#endif

	// use IColor::runtimeGuiColor()
	SystemColor systemColor() const;

	// use IColor::predefinedColor
	Color value() const;

#endif // IC_OBSOLETE

};

#if (IC_OBSOLETE <= IC_OBSOLETE_3)
// global macro to make name change easier:
//#define IBasicColor IBaseColor
class IBasicColor : public IBaseColor {
public:

	IBasicColor();
	IBasicColor(EPredefinedColor commonlyUsedColor);
	IBasicColor(CharIntensity gray, CharIntensity opacity = 255);
	IBasicColor(const IBasicColor&);
	IBasicColor(
		CharIntensity red,
		CharIntensity green,
		CharIntensity blue,
		CharIntensity opacity = 255);

	virtual ~IBasicColor();

	CharIntensity red() const;
	CharIntensity green() const;
	CharIntensity blue() const;

	virtual void red(GIntensity& red) const;
	virtual void green(GIntensity& green) const;
	virtual void blue(GIntensity& blue) const;

	IBasicColor(const IColor&);

	operator IColor();
};
#endif // IC_OBSOLETE

#pragma pack(pop)
#pragma enum(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#include <ibcolor.inl>

#endif
