1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #include "SDL_video.h" 25 #include "SDL_blit.h" 26 27 /* Functions to blit from bitmaps to other surfaces */ 28 29 static void BlitBto1(SDL_BlitInfo *info) 30 { 31 int c; 32 int width, height; 33 Uint8 *src, *map, *dst; 34 int srcskip, dstskip; 35 36 /* Set up some basic variables */ 37 width = info->d_width; 38 height = info->d_height; 39 src = info->s_pixels; 40 srcskip = info->s_skip; 41 dst = info->d_pixels; 42 dstskip = info->d_skip; 43 map = info->table; 44 srcskip += width-(width+7)/8; 45 46 if ( map ) { 47 while ( height-- ) { 48 Uint8 byte = 0, bit; 49 for ( c=0; c<width; ++c ) { 50 if ( (c&7) == 0 ) { 51 byte = *src++; 52 } 53 bit = (byte&0x80)>>7; 54 if ( 1 ) { 55 *dst = map[bit]; 56 } 57 dst++; 58 byte <<= 1; 59 } 60 src += srcskip; 61 dst += dstskip; 62 } 63 } else { 64 while ( height-- ) { 65 Uint8 byte = 0, bit; 66 for ( c=0; c<width; ++c ) { 67 if ( (c&7) == 0 ) { 68 byte = *src++; 69 } 70 bit = (byte&0x80)>>7; 71 if ( 1 ) { 72 *dst = bit; 73 } 74 dst++; 75 byte <<= 1; 76 } 77 src += srcskip; 78 dst += dstskip; 79 } 80 } 81 } 82 static void BlitBto2(SDL_BlitInfo *info) 83 { 84 int c; 85 int width, height; 86 Uint8 *src; 87 Uint16 *map, *dst; 88 int srcskip, dstskip; 89 90 /* Set up some basic variables */ 91 width = info->d_width; 92 height = info->d_height; 93 src = info->s_pixels; 94 srcskip = info->s_skip; 95 dst = (Uint16 *)info->d_pixels; 96 dstskip = info->d_skip/2; 97 map = (Uint16 *)info->table; 98 srcskip += width-(width+7)/8; 99 100 while ( height-- ) { 101 Uint8 byte = 0, bit; 102 for ( c=0; c<width; ++c ) { 103 if ( (c&7) == 0 ) { 104 byte = *src++; 105 } 106 bit = (byte&0x80)>>7; 107 if ( 1 ) { 108 *dst = map[bit]; 109 } 110 byte <<= 1; 111 dst++; 112 } 113 src += srcskip; 114 dst += dstskip; 115 } 116 } 117 static void BlitBto3(SDL_BlitInfo *info) 118 { 119 int c, o; 120 int width, height; 121 Uint8 *src, *map, *dst; 122 int srcskip, dstskip; 123 124 /* Set up some basic variables */ 125 width = info->d_width; 126 height = info->d_height; 127 src = info->s_pixels; 128 srcskip = info->s_skip; 129 dst = info->d_pixels; 130 dstskip = info->d_skip; 131 map = info->table; 132 srcskip += width-(width+7)/8; 133 134 while ( height-- ) { 135 Uint8 byte = 0, bit; 136 for ( c=0; c<width; ++c ) { 137 if ( (c&7) == 0 ) { 138 byte = *src++; 139 } 140 bit = (byte&0x80)>>7; 141 if ( 1 ) { 142 o = bit * 4; 143 dst[0] = map[o++]; 144 dst[1] = map[o++]; 145 dst[2] = map[o++]; 146 } 147 byte <<= 1; 148 dst += 3; 149 } 150 src += srcskip; 151 dst += dstskip; 152 } 153 } 154 static void BlitBto4(SDL_BlitInfo *info) 155 { 156 int width, height; 157 Uint8 *src; 158 Uint32 *map, *dst; 159 int srcskip, dstskip; 160 int c; 161 162 /* Set up some basic variables */ 163 width = info->d_width; 164 height = info->d_height; 165 src = info->s_pixels; 166 srcskip = info->s_skip; 167 dst = (Uint32 *)info->d_pixels; 168 dstskip = info->d_skip/4; 169 map = (Uint32 *)info->table; 170 srcskip += width-(width+7)/8; 171 172 while ( height-- ) { 173 Uint8 byte = 0, bit; 174 for ( c=0; c<width; ++c ) { 175 if ( (c&7) == 0 ) { 176 byte = *src++; 177 } 178 bit = (byte&0x80)>>7; 179 if ( 1 ) { 180 *dst = map[bit]; 181 } 182 byte <<= 1; 183 dst++; 184 } 185 src += srcskip; 186 dst += dstskip; 187 } 188 } 189 190 static void BlitBto1Key(SDL_BlitInfo *info) 191 { 192 int width = info->d_width; 193 int height = info->d_height; 194 Uint8 *src = info->s_pixels; 195 Uint8 *dst = info->d_pixels; 196 int srcskip = info->s_skip; 197 int dstskip = info->d_skip; 198 Uint32 ckey = info->src->colorkey; 199 Uint8 *palmap = info->table; 200 int c; 201 202 /* Set up some basic variables */ 203 srcskip += width-(width+7)/8; 204 205 if ( palmap ) { 206 while ( height-- ) { 207 Uint8 byte = 0, bit; 208 for ( c=0; c<width; ++c ) { 209 if ( (c&7) == 0 ) { 210 byte = *src++; 211 } 212 bit = (byte&0x80)>>7; 213 if ( bit != ckey ) { 214 *dst = palmap[bit]; 215 } 216 dst++; 217 byte <<= 1; 218 } 219 src += srcskip; 220 dst += dstskip; 221 } 222 } else { 223 while ( height-- ) { 224 Uint8 byte = 0, bit; 225 for ( c=0; c<width; ++c ) { 226 if ( (c&7) == 0 ) { 227 byte = *src++; 228 } 229 bit = (byte&0x80)>>7; 230 if ( bit != ckey ) { 231 *dst = bit; 232 } 233 dst++; 234 byte <<= 1; 235 } 236 src += srcskip; 237 dst += dstskip; 238 } 239 } 240 } 241 242 static void BlitBto2Key(SDL_BlitInfo *info) 243 { 244 int width = info->d_width; 245 int height = info->d_height; 246 Uint8 *src = info->s_pixels; 247 Uint16 *dstp = (Uint16 *)info->d_pixels; 248 int srcskip = info->s_skip; 249 int dstskip = info->d_skip; 250 Uint32 ckey = info->src->colorkey; 251 Uint8 *palmap = info->table; 252 int c; 253 254 /* Set up some basic variables */ 255 srcskip += width-(width+7)/8; 256 dstskip /= 2; 257 258 while ( height-- ) { 259 Uint8 byte = 0, bit; 260 for ( c=0; c<width; ++c ) { 261 if ( (c&7) == 0 ) { 262 byte = *src++; 263 } 264 bit = (byte&0x80)>>7; 265 if ( bit != ckey ) { 266 *dstp=((Uint16 *)palmap)[bit]; 267 } 268 byte <<= 1; 269 dstp++; 270 } 271 src += srcskip; 272 dstp += dstskip; 273 } 274 } 275 276 static void BlitBto3Key(SDL_BlitInfo *info) 277 { 278 int width = info->d_width; 279 int height = info->d_height; 280 Uint8 *src = info->s_pixels; 281 Uint8 *dst = info->d_pixels; 282 int srcskip = info->s_skip; 283 int dstskip = info->d_skip; 284 Uint32 ckey = info->src->colorkey; 285 Uint8 *palmap = info->table; 286 int c; 287 288 /* Set up some basic variables */ 289 srcskip += width-(width+7)/8; 290 291 while ( height-- ) { 292 Uint8 byte = 0, bit; 293 for ( c=0; c<width; ++c ) { 294 if ( (c&7) == 0 ) { 295 byte = *src++; 296 } 297 bit = (byte&0x80)>>7; 298 if ( bit != ckey ) { 299 SDL_memcpy(dst, &palmap[bit*4], 3); 300 } 301 byte <<= 1; 302 dst += 3; 303 } 304 src += srcskip; 305 dst += dstskip; 306 } 307 } 308 309 static void BlitBto4Key(SDL_BlitInfo *info) 310 { 311 int width = info->d_width; 312 int height = info->d_height; 313 Uint8 *src = info->s_pixels; 314 Uint32 *dstp = (Uint32 *)info->d_pixels; 315 int srcskip = info->s_skip; 316 int dstskip = info->d_skip; 317 Uint32 ckey = info->src->colorkey; 318 Uint8 *palmap = info->table; 319 int c; 320 321 /* Set up some basic variables */ 322 srcskip += width-(width+7)/8; 323 dstskip /= 4; 324 325 while ( height-- ) { 326 Uint8 byte = 0, bit; 327 for ( c=0; c<width; ++c ) { 328 if ( (c&7) == 0 ) { 329 byte = *src++; 330 } 331 bit = (byte&0x80)>>7; 332 if ( bit != ckey ) { 333 *dstp=((Uint32 *)palmap)[bit]; 334 } 335 byte <<= 1; 336 dstp++; 337 } 338 src += srcskip; 339 dstp += dstskip; 340 } 341 } 342 343 static void BlitBtoNAlpha(SDL_BlitInfo *info) 344 { 345 int width = info->d_width; 346 int height = info->d_height; 347 Uint8 *src = info->s_pixels; 348 Uint8 *dst = info->d_pixels; 349 int srcskip = info->s_skip; 350 int dstskip = info->d_skip; 351 const SDL_Color *srcpal = info->src->palette->colors; 352 SDL_PixelFormat *dstfmt = info->dst; 353 int dstbpp; 354 int c; 355 const int A = info->src->alpha; 356 357 /* Set up some basic variables */ 358 dstbpp = dstfmt->BytesPerPixel; 359 srcskip += width-(width+7)/8; 360 361 while ( height-- ) { 362 Uint8 byte = 0, bit; 363 for ( c=0; c<width; ++c ) { 364 if ( (c&7) == 0 ) { 365 byte = *src++; 366 } 367 bit = (byte&0x80)>>7; 368 if ( 1 ) { 369 Uint32 pixel; 370 unsigned sR, sG, sB; 371 unsigned dR, dG, dB; 372 sR = srcpal[bit].r; 373 sG = srcpal[bit].g; 374 sB = srcpal[bit].b; 375 DISEMBLE_RGB(dst, dstbpp, dstfmt, 376 pixel, dR, dG, dB); 377 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); 378 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); 379 } 380 byte <<= 1; 381 dst += dstbpp; 382 } 383 src += srcskip; 384 dst += dstskip; 385 } 386 } 387 388 static void BlitBtoNAlphaKey(SDL_BlitInfo *info) 389 { 390 int width = info->d_width; 391 int height = info->d_height; 392 Uint8 *src = info->s_pixels; 393 Uint8 *dst = info->d_pixels; 394 int srcskip = info->s_skip; 395 int dstskip = info->d_skip; 396 SDL_PixelFormat *srcfmt = info->src; 397 SDL_PixelFormat *dstfmt = info->dst; 398 const SDL_Color *srcpal = srcfmt->palette->colors; 399 int dstbpp; 400 int c; 401 const int A = srcfmt->alpha; 402 Uint32 ckey = srcfmt->colorkey; 403 404 /* Set up some basic variables */ 405 dstbpp = dstfmt->BytesPerPixel; 406 srcskip += width-(width+7)/8; 407 408 while ( height-- ) { 409 Uint8 byte = 0, bit; 410 for ( c=0; c<width; ++c ) { 411 if ( (c&7) == 0 ) { 412 byte = *src++; 413 } 414 bit = (byte&0x80)>>7; 415 if ( bit != ckey ) { 416 int sR, sG, sB; 417 int dR, dG, dB; 418 Uint32 pixel; 419 sR = srcpal[bit].r; 420 sG = srcpal[bit].g; 421 sB = srcpal[bit].b; 422 DISEMBLE_RGB(dst, dstbpp, dstfmt, 423 pixel, dR, dG, dB); 424 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); 425 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); 426 } 427 byte <<= 1; 428 dst += dstbpp; 429 } 430 src += srcskip; 431 dst += dstskip; 432 } 433 } 434 435 static SDL_loblit bitmap_blit[] = { 436 NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4 437 }; 438 439 static SDL_loblit colorkey_blit[] = { 440 NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key 441 }; 442 443 SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index) 444 { 445 int which; 446 447 if ( surface->format->BitsPerPixel != 1 ) { 448 /* We don't support sub 8-bit packed pixel modes */ 449 return NULL; 450 } 451 if ( surface->map->dst->format->BitsPerPixel < 8 ) { 452 which = 0; 453 } else { 454 which = surface->map->dst->format->BytesPerPixel; 455 } 456 switch(blit_index) { 457 case 0: /* copy */ 458 return bitmap_blit[which]; 459 460 case 1: /* colorkey */ 461 return colorkey_blit[which]; 462 463 case 2: /* alpha */ 464 return which >= 2 ? BlitBtoNAlpha : NULL; 465 466 case 4: /* alpha + colorkey */ 467 return which >= 2 ? BlitBtoNAlphaKey : NULL; 468 } 469 return NULL; 470 } 471 472