| /* | 
 |   Simple DirectMedia Layer | 
 |   Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org> | 
 |  | 
 |   This software is provided 'as-is', without any express or implied | 
 |   warranty.  In no event will the authors be held liable for any damages | 
 |   arising from the use of this software. | 
 |  | 
 |   Permission is granted to anyone to use this software for any purpose, | 
 |   including commercial applications, and to alter it and redistribute it | 
 |   freely, subject to the following restrictions: | 
 |  | 
 |   1. The origin of this software must not be misrepresented; you must not | 
 |      claim that you wrote the original software. If you use this software | 
 |      in a product, an acknowledgment in the product documentation would be | 
 |      appreciated but is not required. | 
 |   2. Altered source versions must be plainly marked as such, and must not be | 
 |      misrepresented as being the original software. | 
 |   3. This notice may not be removed or altered from any source distribution. | 
 | */ | 
 | #include "../SDL_internal.h" | 
 |  | 
 | #include "SDL_video.h" | 
 | #include "SDL_blit.h" | 
 |  | 
 | /* Functions to blit from bitmaps to other surfaces */ | 
 |  | 
 | static void | 
 | BlitBto1(SDL_BlitInfo * info) | 
 | { | 
 |     int c; | 
 |     int width, height; | 
 |     Uint8 *src, *map, *dst; | 
 |     int srcskip, dstskip; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     width = info->dst_w; | 
 |     height = info->dst_h; | 
 |     src = info->src; | 
 |     srcskip = info->src_skip; | 
 |     dst = info->dst; | 
 |     dstskip = info->dst_skip; | 
 |     map = info->table; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     if (map) { | 
 |         while (height--) { | 
 |             Uint8 byte = 0, bit; | 
 |             for (c = 0; c < width; ++c) { | 
 |                 if ((c & 7) == 0) { | 
 |                     byte = *src++; | 
 |                 } | 
 |                 bit = (byte & 0x80) >> 7; | 
 |                 if (1) { | 
 |                     *dst = map[bit]; | 
 |                 } | 
 |                 dst++; | 
 |                 byte <<= 1; | 
 |             } | 
 |             src += srcskip; | 
 |             dst += dstskip; | 
 |         } | 
 |     } else { | 
 |         while (height--) { | 
 |             Uint8 byte = 0, bit; | 
 |             for (c = 0; c < width; ++c) { | 
 |                 if ((c & 7) == 0) { | 
 |                     byte = *src++; | 
 |                 } | 
 |                 bit = (byte & 0x80) >> 7; | 
 |                 if (1) { | 
 |                     *dst = bit; | 
 |                 } | 
 |                 dst++; | 
 |                 byte <<= 1; | 
 |             } | 
 |             src += srcskip; | 
 |             dst += dstskip; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto2(SDL_BlitInfo * info) | 
 | { | 
 |     int c; | 
 |     int width, height; | 
 |     Uint8 *src; | 
 |     Uint16 *map, *dst; | 
 |     int srcskip, dstskip; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     width = info->dst_w; | 
 |     height = info->dst_h; | 
 |     src = info->src; | 
 |     srcskip = info->src_skip; | 
 |     dst = (Uint16 *) info->dst; | 
 |     dstskip = info->dst_skip / 2; | 
 |     map = (Uint16 *) info->table; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (1) { | 
 |                 *dst = map[bit]; | 
 |             } | 
 |             byte <<= 1; | 
 |             dst++; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto3(SDL_BlitInfo * info) | 
 | { | 
 |     int c, o; | 
 |     int width, height; | 
 |     Uint8 *src, *map, *dst; | 
 |     int srcskip, dstskip; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     width = info->dst_w; | 
 |     height = info->dst_h; | 
 |     src = info->src; | 
 |     srcskip = info->src_skip; | 
 |     dst = info->dst; | 
 |     dstskip = info->dst_skip; | 
 |     map = info->table; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (1) { | 
 |                 o = bit * 4; | 
 |                 dst[0] = map[o++]; | 
 |                 dst[1] = map[o++]; | 
 |                 dst[2] = map[o++]; | 
 |             } | 
 |             byte <<= 1; | 
 |             dst += 3; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto4(SDL_BlitInfo * info) | 
 | { | 
 |     int width, height; | 
 |     Uint8 *src; | 
 |     Uint32 *map, *dst; | 
 |     int srcskip, dstskip; | 
 |     int c; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     width = info->dst_w; | 
 |     height = info->dst_h; | 
 |     src = info->src; | 
 |     srcskip = info->src_skip; | 
 |     dst = (Uint32 *) info->dst; | 
 |     dstskip = info->dst_skip / 4; | 
 |     map = (Uint32 *) info->table; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (1) { | 
 |                 *dst = map[bit]; | 
 |             } | 
 |             byte <<= 1; | 
 |             dst++; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto1Key(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint8 *dst = info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     Uint32 ckey = info->colorkey; | 
 |     Uint8 *palmap = info->table; | 
 |     int c; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     if (palmap) { | 
 |         while (height--) { | 
 |             Uint8 byte = 0, bit; | 
 |             for (c = 0; c < width; ++c) { | 
 |                 if ((c & 7) == 0) { | 
 |                     byte = *src++; | 
 |                 } | 
 |                 bit = (byte & 0x80) >> 7; | 
 |                 if (bit != ckey) { | 
 |                     *dst = palmap[bit]; | 
 |                 } | 
 |                 dst++; | 
 |                 byte <<= 1; | 
 |             } | 
 |             src += srcskip; | 
 |             dst += dstskip; | 
 |         } | 
 |     } else { | 
 |         while (height--) { | 
 |             Uint8 byte = 0, bit; | 
 |             for (c = 0; c < width; ++c) { | 
 |                 if ((c & 7) == 0) { | 
 |                     byte = *src++; | 
 |                 } | 
 |                 bit = (byte & 0x80) >> 7; | 
 |                 if (bit != ckey) { | 
 |                     *dst = bit; | 
 |                 } | 
 |                 dst++; | 
 |                 byte <<= 1; | 
 |             } | 
 |             src += srcskip; | 
 |             dst += dstskip; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto2Key(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint16 *dstp = (Uint16 *) info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     Uint32 ckey = info->colorkey; | 
 |     Uint8 *palmap = info->table; | 
 |     int c; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     srcskip += width - (width + 7) / 8; | 
 |     dstskip /= 2; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (bit != ckey) { | 
 |                 *dstp = ((Uint16 *) palmap)[bit]; | 
 |             } | 
 |             byte <<= 1; | 
 |             dstp++; | 
 |         } | 
 |         src += srcskip; | 
 |         dstp += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto3Key(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint8 *dst = info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     Uint32 ckey = info->colorkey; | 
 |     Uint8 *palmap = info->table; | 
 |     int c; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (bit != ckey) { | 
 |                 SDL_memcpy(dst, &palmap[bit * 4], 3); | 
 |             } | 
 |             byte <<= 1; | 
 |             dst += 3; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBto4Key(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint32 *dstp = (Uint32 *) info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     Uint32 ckey = info->colorkey; | 
 |     Uint8 *palmap = info->table; | 
 |     int c; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     srcskip += width - (width + 7) / 8; | 
 |     dstskip /= 4; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (bit != ckey) { | 
 |                 *dstp = ((Uint32 *) palmap)[bit]; | 
 |             } | 
 |             byte <<= 1; | 
 |             dstp++; | 
 |         } | 
 |         src += srcskip; | 
 |         dstp += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBtoNAlpha(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint8 *dst = info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     const SDL_Color *srcpal = info->src_fmt->palette->colors; | 
 |     SDL_PixelFormat *dstfmt = info->dst_fmt; | 
 |     int dstbpp; | 
 |     int c; | 
 |     Uint32 pixel; | 
 |     unsigned sR, sG, sB; | 
 |     unsigned dR, dG, dB, dA; | 
 |     const unsigned A = info->a; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     dstbpp = dstfmt->BytesPerPixel; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (1) { | 
 |                 sR = srcpal[bit].r; | 
 |                 sG = srcpal[bit].g; | 
 |                 sB = srcpal[bit].b; | 
 |                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); | 
 |                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); | 
 |                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); | 
 |             } | 
 |             byte <<= 1; | 
 |             dst += dstbpp; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | BlitBtoNAlphaKey(SDL_BlitInfo * info) | 
 | { | 
 |     int width = info->dst_w; | 
 |     int height = info->dst_h; | 
 |     Uint8 *src = info->src; | 
 |     Uint8 *dst = info->dst; | 
 |     int srcskip = info->src_skip; | 
 |     int dstskip = info->dst_skip; | 
 |     SDL_PixelFormat *srcfmt = info->src_fmt; | 
 |     SDL_PixelFormat *dstfmt = info->dst_fmt; | 
 |     const SDL_Color *srcpal = srcfmt->palette->colors; | 
 |     int dstbpp; | 
 |     int c; | 
 |     Uint32 pixel; | 
 |     unsigned sR, sG, sB; | 
 |     unsigned dR, dG, dB, dA; | 
 |     const unsigned A = info->a; | 
 |     Uint32 ckey = info->colorkey; | 
 |  | 
 |     /* Set up some basic variables */ | 
 |     dstbpp = dstfmt->BytesPerPixel; | 
 |     srcskip += width - (width + 7) / 8; | 
 |  | 
 |     while (height--) { | 
 |         Uint8 byte = 0, bit; | 
 |         for (c = 0; c < width; ++c) { | 
 |             if ((c & 7) == 0) { | 
 |                 byte = *src++; | 
 |             } | 
 |             bit = (byte & 0x80) >> 7; | 
 |             if (bit != ckey) { | 
 |                 sR = srcpal[bit].r; | 
 |                 sG = srcpal[bit].g; | 
 |                 sB = srcpal[bit].b; | 
 |                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); | 
 |                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); | 
 |                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); | 
 |             } | 
 |             byte <<= 1; | 
 |             dst += dstbpp; | 
 |         } | 
 |         src += srcskip; | 
 |         dst += dstskip; | 
 |     } | 
 | } | 
 |  | 
 | static const SDL_BlitFunc bitmap_blit[] = { | 
 |     (SDL_BlitFunc) NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4 | 
 | }; | 
 |  | 
 | static const SDL_BlitFunc colorkey_blit[] = { | 
 |     (SDL_BlitFunc) NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key | 
 | }; | 
 |  | 
 | SDL_BlitFunc | 
 | SDL_CalculateBlit0(SDL_Surface * surface) | 
 | { | 
 |     int which; | 
 |  | 
 |     if (surface->format->BitsPerPixel != 1) { | 
 |         /* We don't support sub 8-bit packed pixel modes */ | 
 |         return (SDL_BlitFunc) NULL; | 
 |     } | 
 |     if (surface->map->dst->format->BitsPerPixel < 8) { | 
 |         which = 0; | 
 |     } else { | 
 |         which = surface->map->dst->format->BytesPerPixel; | 
 |     } | 
 |     switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { | 
 |     case 0: | 
 |         return bitmap_blit[which]; | 
 |  | 
 |     case SDL_COPY_COLORKEY: | 
 |         return colorkey_blit[which]; | 
 |  | 
 |     case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: | 
 |         return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc) NULL; | 
 |  | 
 |     case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: | 
 |         return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc) NULL; | 
 |     } | 
 |     return (SDL_BlitFunc) NULL; | 
 | } | 
 |  | 
 | /* vi: set ts=4 sw=4 expandtab: */ |