/* Starshatter OpenSource Distribution Copyright (c) 1997-2004, Destroyer Studios LLC. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name "Destroyer Studios" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SUBSYSTEM: nGenEx.lib FILE: Color.h AUTHOR: John DiCamillo OVERVIEW ======== Universal Color Format class */ #ifndef Color_h #define Color_h #include "Types.h" // +--------------------------------------------------------------------+ class Video; // +--------------------------------------------------------------------+ struct ColorFormat { ColorFormat(int palsize) : pal(palsize), bpp(8), rdown(0), rshift(0), rmask(0), gdown(0), gshift(0), gmask(0), bdown(0), bshift(0), bmask(0), adown(0), ashift(0), amask(0) { } ColorFormat(int size, BYTE r, BYTE rs, BYTE g, BYTE gs, BYTE b, BYTE bs, BYTE a=0, BYTE as=0) : pal(0), bpp(size), rdown(8-r), rshift(rs), rmask(((1<> RShift; } DWORD Green() const { return (rgba & GMask) >> GShift; } DWORD Blue() const { return (rgba & BMask) >> BShift; } DWORD Alpha() const { return (rgba & AMask) >> AShift; } float fRed() const { return (float)(Red() /255.0); } float fGreen() const { return (float)(Green()/255.0); } float fBlue() const { return (float)(Blue() /255.0); } float fAlpha() const { return (float)(Alpha()/255.0); } BYTE Index() const { return table[((rgba&RMask)>>(RShift+3)<<10)| ((rgba&GMask)>>(GShift+3)<< 5)| ((rgba&BMask)>>(BShift+3))]; } inline BYTE IndexedBlend(BYTE dst) const; static DWORD FormattedBlend(DWORD c1, DWORD c2); DWORD TextureFormat(int keep_alpha=0) const; DWORD Formatted() const; DWORD Unfaded() const; Color ShadeColor(int shade) const; DWORD Shaded(int shade) const; Color Faded() const; // some useful colors static Color White; static Color Black; static Color Gray; static Color LightGray; static Color DarkGray; static Color BrightRed; static Color BrightBlue; static Color BrightGreen; static Color DarkRed; static Color DarkBlue; static Color DarkGreen; static Color Yellow; static Color Cyan; static Color Magenta; static Color Tan; static Color Brown; static Color Violet; static Color Orange; static void UseVideo(Video* v); static void UseFormat(const ColorFormat& cf); static void UseTextureFormat(const ColorFormat& cf, int alpha_level=0); static void WithTextureFormat(int alpha_level=0); static void SetPalette(PALETTEENTRY* pal, int palsize, BYTE* invpal=0); static void SavePalette(const char* basename); static void SetFade(double f, Color c=Black, int build_shade=false); static const ColorFormat& GetTextureFormat(int alpha_level=0) { return texture_format[alpha_level]; } static const ColorFormat& GetScreenFormat() { return format; } // indexed color initialization: static void BuildShadeTable(); static void SaveShadeTable(const char* basename); static void BuildBlendTable(); static double GetFade() { return fade; } static Color GetFadeColor() { return fade_color; } static Color Scale(const Color& c1, const Color& c2, double scale); static Color Unformat(DWORD formatted_color); private: DWORD rgba; static bool standard_format; static PALETTEENTRY palette[256]; static BYTE table[32768]; static ColorFormat format; static int texture_alpha_level; static ColorFormat texture_format[4]; static double fade; static Color fade_color; static Video* video; }; // +--------------------------------------------------------------------+ class ColorValue { friend class Color; public: static const char* TYPENAME() { return "ColorValue"; } ColorValue() : r(0), g(0), b(0), a(0) { } ColorValue(const ColorValue& c) : r(c.r), g(c.g), b(c.b), a(c.a) { } ColorValue(const Color& c) : r( c.fRed() ), g( c.fGreen() ), b( c.fBlue() ), a( c.fAlpha() ) { } ColorValue(float ar, float ag, float ab, float aa=1.0f) : r(ar), g(ag), b(ab), a(aa) { } int operator==(const ColorValue& c) const { return r==c.r && g==c.g && b==c.b && a==c.a; } int operator!=(const ColorValue& c) const { return r!=c.r || g!=c.g || b!=c.b || a!=c.a; } ColorValue& operator+=(const ColorValue& c); // simple summation ColorValue operator+(const ColorValue& c) const; // color alpha blending ColorValue operator*(const ColorValue& c) const; // color modulation ColorValue operator*(double scale) const; ColorValue dim(double scale) const; void Set(float ar, float ag, float ab, float aa=1.0f) { r=ar; g=ag; b=ab; a=aa; } void SetRed(float ar) { r=ar; } void SetGreen(float ag) { g=ag; } void SetBlue(float ab) { b=ab; } void SetAlpha(float aa) { a=aa; } float Red() const { return r; } float Green() const { return g; } float Blue() const { return b; } float Alpha() const { return a; } Color ToColor() const; DWORD TextureFormat(int keep_alpha=0) const { return ToColor().TextureFormat(keep_alpha); } DWORD Formatted() const { return ToColor().Formatted(); } DWORD Unfaded() const { return ToColor().Unfaded(); } Color ShadeColor(int shade) const { return ToColor().ShadeColor(shade); } DWORD Shaded(int shade) const { return ToColor().Shaded(shade); } Color Faded() const { return ToColor().Faded(); } private: float r, g, b, a; }; // +--------------------------------------------------------------------+ class ColorIndex { friend class Color; public: static const char* TYPENAME() { return "ColorIndex"; } ColorIndex() : index(0) { } ColorIndex(const ColorIndex& c) : index(c.index) { } ColorIndex(BYTE r, BYTE g, BYTE b) { index = Color(r,g,b).Index(); } ColorIndex(BYTE i) : index(i) { } ColorIndex& operator= (const ColorIndex& c) { index = c.index; return *this; } int operator==(const ColorIndex& c) const { return index == c.index; } int operator!=(const ColorIndex& c) const { return index != c.index; } BYTE Index() const { return index; } DWORD Red() const { return Color::palette[index].peRed; } DWORD Green() const { return Color::palette[index].peGreen; } DWORD Blue() const { return Color::palette[index].peBlue; } float fRed() const { return (float)(Red() /255.0); } float fGreen() const { return (float)(Green()/255.0); } float fBlue() const { return (float)(Blue() /255.0); } DWORD TextureFormat() const { return texture_palette[index]; } DWORD Unfaded() const { return unfaded_palette[index]; } DWORD Formatted() const { return formatted_palette[index]; } DWORD Shaded(int shade) const { return shade_table[shade*256+index]; } ColorIndex Faded() const { return ColorIndex(index); } // note: this will only work in 8-bit color mode... ColorIndex ShadeColor(int s) const { return ColorIndex((BYTE)(shade_table[s*256+index])); } // for poly shading optimization static DWORD* ShadeTable() { return shade_table; } BYTE IndexedBlend(BYTE dst) const { return blend_table[dst*256+index]; } private: BYTE index; static DWORD* texture_palette; static DWORD texture_palettes[4][256]; static DWORD unfaded_palette[256]; static DWORD formatted_palette[256]; static DWORD shade_table[256*256]; static BYTE blend_table[256*256]; }; inline BYTE Color::IndexedBlend(BYTE dst) const { return ColorIndex::blend_table[dst*256+Index()]; } #endif // Color_h