# 32bpp_base.hpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD 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, version 2.
    00006  * OpenTTD 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.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #ifndef BLITTER_32BPP_BASE_HPP
    00013 #define BLITTER_32BPP_BASE_HPP
    00014
    00015 #include "base.hpp"
    00016 #include "../core/bitmath_func.hpp"
    00017 #include "../core/math_func.hpp"
    00018 #include "../gfx_func.h"
    00019 #include "../debug.h"
    00020 #include <math.h>
    00021
    00022 extern int _sat, _li;
    00023
    00024 class Blitter_32bppBase : public Blitter {
    00025 public:
    00026   /* virtual */ uint8 GetScreenDepth() { return 32; }
    00027 //  /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
    00028 //  /* virtual */ void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal);
    00029 //  /* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, AllocatorProc *allocator);
    00030   /* virtual */ void *MoveTo(const void *video, int x, int y);
    00031   /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour);
    00032   /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour);
    00033   /* virtual */ void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour);
    00034   /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height);
    00035   /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height);
    00036   /* virtual */ void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
    00037   /* virtual */ void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y);
    00038   /* virtual */ int BufferSize(int width, int height);
    00039   /* virtual */ void PaletteAnimate(uint start, uint count);
    00040   /* virtual */ Blitter::PaletteAnimation UsePaletteAnimation();
    00041   /* virtual */ int GetBytesPerPixel() { return 4; }
    00042
    00046   static inline uint32 ComposeColour(uint a, uint r, uint g, uint b)
    00047   {
    00048     return (((a) << 24) & 0xFF000000) | (((r) << 16) & 0x00FF0000) | (((g) << 8) & 0x0000FF00) | ((b) & 0x000000FF);
    00049   }
    00050
    00054   static inline uint32 LookupColourInPalette(uint index)
    00055   {
    00056     return _cur_palette[index].data;
    00057   }
    00058
    00062   static inline uint32 ComposeColourRGBANoCheck(uint r, uint g, uint b, uint a, uint32 current)
    00063   {
    00064     uint cr = GB(current, 16, 8);
    00065     uint cg = GB(current, 8,  8);
    00066     uint cb = GB(current, 0,  8);
    00067
    00068     /* The 256 is wrong, it should be 255, but 256 is much faster... */
    00069     return ComposeColour(0xFF,
    00070               ((int)(r - cr) * a) / 256 + cr,
    00071               ((int)(g - cg) * a) / 256 + cg,
    00072               ((int)(b - cb) * a) / 256 + cb);
    00073   }
    00074
    00079   static inline uint32 ComposeColourRGBA(uint r, uint g, uint b, uint a, uint32 current)
    00080   {
    00081     if (a == 0) return current;
    00082     if (a >= 255) return ComposeColour(0xFF, r, g, b);
    00083
    00084     return ComposeColourRGBANoCheck(r, g, b, a, current);
    00085   }
    00086
    00090   static inline uint32 ComposeColourPANoCheck(uint32 colour, uint a, uint32 current)
    00091   {
    00092     uint r  = GB(colour,  16, 8);
    00093     uint g  = GB(colour,  8,  8);
    00094     uint b  = GB(colour,  0,  8);
    00095
    00096     return ComposeColourRGBANoCheck(r, g, b, a, current);
    00097   }
    00098
    00103   static inline uint32 ComposeColourPA(uint32 colour, uint a, uint32 current)
    00104   {
    00105     if (a == 0) return current;
    00106     if (a >= 255) return (colour | 0xFF000000);
    00107
    00108     return ComposeColourPANoCheck(colour, a, current);
    00109   }
    00110
    00114   static inline uint ComposeColourBlend(uint colour, uint32 current)
    00115   {
    00116     if (colour == current) return colour;
    00117
    00118     /* Converting to HSL */
    00119
    00120     /* Colour (cc) */
    00121     int r_colour = GB(colour,  16, 8);
    00122     int g_colour = GB(colour,  8,  8);
    00123     int b_colour = GB(colour,  0,  8);
    00124     int hue = 0;
    00125     int saturation = 0;
    00126     int lightness_colour = 0;
    00127
    00128     /* Find max and min cc */
    00129     int min_colour = min(min(r_colour, g_colour),b_colour);
    00130
    00131     if ((r_colour > g_colour) && (r_colour > b_colour)) {
    00132       if (min_colour != r_colour) {
    00133         hue = 60 * (g_colour - b_colour) / (r_colour - min_colour) + 360;
    00134         hue %= 360;
    00135         if ((r_colour + min_colour) <= 256) {
    00136           saturation = (r_colour - min_colour) * 255 / (r_colour + min_colour);
    00137         } else {
    00138           saturation = (r_colour - min_colour) * 255 / (512 - (r_colour + min_colour));
    00139         }
    00140       } else {
    00141         saturation = 0;
    00142         lightness_colour = r_colour;
    00143       }
    00144     } else if (g_colour > b_colour){
    00145       if (min_colour != g_colour) {
    00146         hue = 60 * (b_colour - r_colour) / (g_colour - min_colour) + 120;
    00147         if ((g_colour + min_colour) <= 256) {
    00148           saturation = (g_colour - min_colour) * 255 / (g_colour + min_colour);
    00149         } else {
    00150           saturation = (g_colour - min_colour) * 255 / (512 - (g_colour + min_colour));
    00151         }
    00152       } else {
    00153         saturation = 0;
    00154         lightness_colour = g_colour;
    00155       }
    00156     } else {
    00157       if (min_colour != b_colour) {
    00158         hue = 60 * (r_colour - g_colour) / (b_colour - min_colour) + 240;
    00159         if ((b_colour + min_colour) <= 256) {
    00160           saturation = (b_colour - min_colour) * 255 / (b_colour + min_colour);
    00161         } else {
    00162           saturation = (b_colour - min_colour) * 255 / (512 - (b_colour + min_colour));
    00163         }
    00164       } else {
    00165         saturation = 0;
    00166         lightness_colour = b_colour;
    00167       }
    00168     }
    00169
    00170     /* Original colour */
    00171     int r_current = GB(current,  16, 8);
    00172     int g_current = GB(current,  8,  8);
    00173     int b_current = GB(current,  0,  8);
    00174     /* Find max and min original colour */
    00175     int min_current = min(min(r_current, g_current),b_current);
    00176     int max_current = max(max(r_current, g_current),b_current);
    00177
    00178     /* Lightness original colour */
    00179     int lightness_current = (max_current + min_current) / 2;
    00180
    00181     /* Converting to RGB */
    00182     unsigned int red, green, blue;
    00183
    00184     if (saturation == 0) {
    00185       red = (lightness_colour + lightness_current) / 2;
    00186       green = red;
    00187       blue = red;
    00188     } else {
    00189       float q;
    00190       if (lightness_current < 128) {
    00191         q = lightness_current * (1 + saturation / 255.0);
    00192       } else {
    00193         q = lightness_current + saturation - (lightness_current * saturation / 255.0);
    00194       }
    00195
    00196       float p = (2 * lightness_current) - q;
    00197
    00198       /* Red */
    00199       int hue_r = hue + 120;
    00200       if (hue_r > 360) {
    00201         hue_r -= 360;
    00202       }
    00203       if (hue_r < 60) {
    00204         red = p + ((q - p) * hue_r / 60.0);
    00205       } else if (hue_r < 180){
    00206         red = q;
    00207       } else if (hue_r < 240) {
    00208         red = p + ((q - p) * (4.0 - hue_r / 60.0));
    00209       } else {
    00210         red = p;
    00211       }
    00212
    00213       /* Green */
    00214       int hue_g = hue;
    00215
    00216       if (hue_g < 60) {
    00217         green = p + ((q - p) * hue_g / 60.0);
    00218       } else if (hue_g < 180){
    00219         green = q;
    00220       } else if (hue_g < 240) {
    00221         green = p + ((q - p) * (4.0 - hue_g / 60.0));
    00222       } else {
    00223         green = p;
    00224       }
    00225
    00226       /* Blue */
    00227       int hue_b = hue - 120;
    00228       if (hue_b < 0.0) {
    00229         hue_b += 360;
    00230       }
    00231       if (hue_b < 60) {
    00232         blue = p + ((q - p) * hue_b / 60.0);
    00233       } else if (hue_b < 180){
    00234         blue = q;
    00235       } else if (hue_b < 240) {
    00236         blue = p + ((q - p) * (4.0 - hue_b / 60.0));
    00237       } else {
    00238         blue = p;
    00239       }
    00240     }
    00241
    00242     return ComposeColour(0xff, red, green, blue);
    00243   }
    00244
    00252   static inline uint32 MakeTransparent(uint32 colour, uint nom, uint denom = 256)
    00253   {
    00254     uint r = GB(colour, 16, 8);
    00255     uint g = GB(colour, 8,  8);
    00256     uint b = GB(colour, 0,  8);
    00257
    00258     return ComposeColour(0xFF, r * nom / denom, g * nom / denom, b * nom / denom);
    00259   }
    00260
    00266   static inline uint32 MakeGrey(uint32 colour)
    00267   {
    00268     uint r = GB(colour, 16, 8);
    00269     uint g = GB(colour, 8,  8);
    00270     uint b = GB(colour, 0,  8);
    00271
    00272     /* To avoid doubles and stuff, multiple it with a total of 65536 (16bits), then
    00273      *  divide by it to normalize the value to a byte again. See heightmap.cpp for
    00274      *  information about the formula. */
    00275     colour = ((r * 19595) + (g * 38470) + (b * 7471)) / 65536;
    00276
    00277     return ComposeColour(0xFF, colour, colour, colour);
    00278   }
    00279 };
    00280
    00281 #endif /* BLITTER_32BPP_BASE_HPP */