src/blitter/32bpp_simple.cpp
branchgamebalance
changeset 9913 e79cd19772dd
child 9629 66dde6412125
equal deleted inserted replaced
9912:1ac8aac92385 9913:e79cd19772dd
       
     1 #include "../stdafx.h"
       
     2 #include "../zoom.hpp"
       
     3 #include "../gfx.h"
       
     4 #include "../debug.h"
       
     5 #include "../table/sprites.h"
       
     6 #include "32bpp_simple.hpp"
       
     7 
       
     8 static FBlitter_32bppSimple iFBlitter_32bppSimple;
       
     9 
       
    10 /**
       
    11  * Compose a color based on RGB values.
       
    12  */
       
    13 static inline uint ComposeColor(uint r, uint g, uint b)
       
    14 {
       
    15 	return (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF) << 0;
       
    16 }
       
    17 
       
    18 /**
       
    19  * Compose a color based on RGBA values and the current pixel value.
       
    20  */
       
    21 static inline uint ComposeColorRGBA(uint r, uint g, uint b, uint a, uint current)
       
    22 {
       
    23 	uint cr, cg, cb;
       
    24 	cr = GB(current, 16, 8);
       
    25 	cg = GB(current, 8,  8);
       
    26 	cb = GB(current, 0,  8);
       
    27 
       
    28 	return ComposeColor((r * a + cr * (255 - a)) / 255,
       
    29 											(g * a + cg * (255 - a)) / 255,
       
    30 											(b * a + cb * (255 - a)) / 255);
       
    31 }
       
    32 
       
    33 /**
       
    34  * Compose a color based on Pixel value, alpha value, and the current pixel value.
       
    35  */
       
    36 static inline uint ComposeColorPA(uint color, uint a, uint current)
       
    37 {
       
    38 	uint r, g, b, cr, cg, cb;
       
    39 	r  = GB(color,   16, 8);
       
    40 	g  = GB(color,   8,  8);
       
    41 	b  = GB(color,   0,  8);
       
    42 	cr = GB(current, 16, 8);
       
    43 	cg = GB(current, 8,  8);
       
    44 	cb = GB(current, 0,  8);
       
    45 
       
    46 	return ComposeColor((r * a + cr * (255 - a)) / 255,
       
    47 											(g * a + cg * (255 - a)) / 255,
       
    48 											(b * a + cb * (255 - a)) / 255);
       
    49 }
       
    50 
       
    51 /**
       
    52  * Make a pixel looks like it is transparent.
       
    53  * @param color the color already on the screen.
       
    54  * @param amount the amount of transparency, times 100.
       
    55  * @return the new color for the screen.
       
    56  */
       
    57 static inline uint MakeTransparent(uint color, uint amount)
       
    58 {
       
    59 	uint r, g, b;
       
    60 	r = GB(color, 16, 8);
       
    61 	g = GB(color, 8,  8);
       
    62 	b = GB(color, 0,  8);
       
    63 
       
    64 	return ComposeColor(r * amount / 100, g * amount / 100, b * amount / 100);
       
    65 }
       
    66 
       
    67 /**
       
    68  * Make a color grey-based.
       
    69  * @param color the color to make grey.
       
    70  * @return the new color, now grey.
       
    71  */
       
    72 static inline uint MakeGrey(uint color)
       
    73 {
       
    74 	uint r, g, b;
       
    75 	r = GB(color, 16, 8);
       
    76 	g = GB(color, 8,  8);
       
    77 	b = GB(color, 0,  8);
       
    78 
       
    79 	/* To avoid doubles and stuff, multiple it with a total of 65536 (16bits), then
       
    80 	 *  divide by it to normalize the value to a byte again. See heightmap.cpp for
       
    81 	 *  information about the formula. */
       
    82 	color = ((r * 19595) + (g * 38470) + (b * 7471)) / 65536;
       
    83 
       
    84 	return ComposeColor(color, color, color);
       
    85 }
       
    86 
       
    87 void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
       
    88 {
       
    89 	const SpriteLoader::CommonPixel *src, *src_line;
       
    90 	uint32 *dst, *dst_line;
       
    91 
       
    92 	/* Find where to start reading in the source sprite */
       
    93 	src_line = (const SpriteLoader::CommonPixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
       
    94 	dst_line = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
       
    95 
       
    96 	for (int y = 0; y < bp->height; y++) {
       
    97 		dst = dst_line;
       
    98 		dst_line += bp->pitch;
       
    99 
       
   100 		src = src_line;
       
   101 		src_line += bp->sprite_width * ScaleByZoom(1, zoom);
       
   102 
       
   103 		for (int x = 0; x < bp->width; x++) {
       
   104 			switch (mode) {
       
   105 				case BM_COLOUR_REMAP:
       
   106 					/* In case the m-channel is zero, do not remap this pixel in any way */
       
   107 					if (src->m == 0) {
       
   108 						if (src->a != 0) *dst = ComposeColorRGBA(src->r, src->g, src->b, src->a, *dst);
       
   109 					} else {
       
   110 						if (bp->remap[src->m] != 0) *dst = ComposeColorPA(this->LookupColourInPalette(bp->remap[src->m]), src->a, *dst);
       
   111 					}
       
   112 					break;
       
   113 
       
   114 				case BM_TRANSPARENT:
       
   115 					/* TODO -- We make an assumption here that the remap in fact is transparency, not some color.
       
   116 					 *  This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
       
   117 					 *  we produce a result the newgrf maker didn't expect ;) */
       
   118 
       
   119 					/* Make the current color a bit more black, so it looks like this image is transparent */
       
   120 					if (src->a != 0) *dst = MakeTransparent(*dst, 75);
       
   121 					break;
       
   122 
       
   123 				default:
       
   124 					if (src->a != 0) *dst = ComposeColorRGBA(src->r, src->g, src->b, src->a, *dst);
       
   125 					break;
       
   126 			}
       
   127 			dst++;
       
   128 			src += ScaleByZoom(1, zoom);
       
   129 		}
       
   130 	}
       
   131 }
       
   132 
       
   133 void Blitter_32bppSimple::DrawColorMappingRect(void *dst, int width, int height, int pal)
       
   134 {
       
   135 	uint32 *udst = (uint32 *)dst;
       
   136 
       
   137 	if (pal == PALETTE_TO_TRANSPARENT) {
       
   138 		do {
       
   139 			for (int i = 0; i != width; i++) {
       
   140 				*udst = MakeTransparent(*udst, 60);
       
   141 				udst++;
       
   142 			}
       
   143 			udst = udst - width + _screen.pitch;
       
   144 		} while (height--);
       
   145 		return;
       
   146 	}
       
   147 	if (pal == PALETTE_TO_STRUCT_GREY) {
       
   148 		do {
       
   149 			for (int i = 0; i != width; i++) {
       
   150 				*udst = MakeGrey(*udst);
       
   151 				udst++;
       
   152 			}
       
   153 			udst = udst - width + _screen.pitch;
       
   154 		} while (height--);
       
   155 		return;
       
   156 	}
       
   157 
       
   158 	DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this color table ('%d')", pal);
       
   159 }
       
   160 
       
   161 Sprite *Blitter_32bppSimple::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
       
   162 {
       
   163 	Sprite *dest_sprite;
       
   164 	SpriteLoader::CommonPixel *dst;
       
   165 	dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sprite->height * sprite->width * sizeof(SpriteLoader::CommonPixel));
       
   166 
       
   167 	dest_sprite->height = sprite->height;
       
   168 	dest_sprite->width  = sprite->width;
       
   169 	dest_sprite->x_offs = sprite->x_offs;
       
   170 	dest_sprite->y_offs = sprite->y_offs;
       
   171 
       
   172 	dst = (SpriteLoader::CommonPixel *)dest_sprite->data;
       
   173 
       
   174 	memcpy(dst, sprite->data, sprite->height * sprite->width * sizeof(SpriteLoader::CommonPixel));
       
   175 	for (int i = 0; i < sprite->height * sprite->width; i++) {
       
   176 		if (dst[i].m != 0) {
       
   177 			/* Pre-convert the mapping channel to a RGB value */
       
   178 			uint color = this->LookupColourInPalette(dst[i].m);
       
   179 			dst[i].r = GB(color, 16, 8);
       
   180 			dst[i].g = GB(color, 8,  8);
       
   181 			dst[i].b = GB(color, 0,  8);
       
   182 		}
       
   183 	}
       
   184 
       
   185 	return dest_sprite;
       
   186 }