Fixed bug 2009 - Creating texture from 32-bit surface with colorkey and per-surface alpha ignores the colorkey
authorSam Lantinga <slouken@libsdl.org>
Thu, 08 Aug 2013 02:30:32 -0700
changeset 7601fdf89883bbaa
parent 7600 55afbc8f2a65
child 7602 9829fb1aeac7
Fixed bug 2009 - Creating texture from 32-bit surface with colorkey and per-surface alpha ignores the colorkey

To fix this we need to ignore the alpha channel in the colorkey comparison, which is the way colorkey comparisons are defined in SDL.

We also need to reset the alpha and color modulation when converting a surface.
src/video/SDL_surface.c
     1.1 --- a/src/video/SDL_surface.c	Thu Aug 08 01:59:36 2013 -0700
     1.2 +++ b/src/video/SDL_surface.c	Thu Aug 08 02:30:32 2013 -0700
     1.3 @@ -255,11 +255,13 @@
     1.4              Uint16 ckey = (Uint16) surface->map->info.colorkey;
     1.5              Uint16 mask = (Uint16) (~surface->format->Amask);
     1.6  
     1.7 +            /* Ignore alpha in colorkey comparison */
     1.8 +            ckey &= mask;
     1.9              row = (Uint16 *) surface->pixels;
    1.10              for (y = surface->h; y--;) {
    1.11                  spot = row;
    1.12                  for (x = surface->w; x--;) {
    1.13 -                    if (*spot == ckey) {
    1.14 +                    if ((*spot & mask) == ckey) {
    1.15                          *spot &= mask;
    1.16                      }
    1.17                      ++spot;
    1.18 @@ -277,10 +279,13 @@
    1.19              Uint32 ckey = surface->map->info.colorkey;
    1.20              Uint32 mask = ~surface->format->Amask;
    1.21  
    1.22 +            /* Ignore alpha in colorkey comparison */
    1.23 +            ckey &= mask;
    1.24              row = (Uint32 *) surface->pixels;
    1.25              for (y = surface->h; y--;) {
    1.26                  spot = row;
    1.27                  for (x = surface->w; x--;) {
    1.28 +                    if ((*spot & mask) == ckey) {
    1.29                      if (*spot == ckey) {
    1.30                          *spot &= mask;
    1.31                      }
    1.32 @@ -802,6 +807,7 @@
    1.33  {
    1.34      SDL_Surface *convert;
    1.35      Uint32 copy_flags;
    1.36 +    SDL_Color copy_color;
    1.37      SDL_Rect bounds;
    1.38  
    1.39      /* Check for empty destination palette! (results in empty image) */
    1.40 @@ -838,7 +844,16 @@
    1.41  
    1.42      /* Save the original copy flags */
    1.43      copy_flags = surface->map->info.flags;
    1.44 +    copy_color.r = surface->map->info.r;
    1.45 +    copy_color.g = surface->map->info.g;
    1.46 +    copy_color.b = surface->map->info.b;
    1.47 +    copy_color.a = surface->map->info.a;
    1.48 +    surface->map->info.r = 0xFF;
    1.49 +    surface->map->info.g = 0xFF;
    1.50 +    surface->map->info.b = 0xFF;
    1.51 +    surface->map->info.a = 0xFF;
    1.52      surface->map->info.flags = 0;
    1.53 +    SDL_InvalidateMap(surface->map);
    1.54  
    1.55      /* Copy over the image data */
    1.56      bounds.x = 0;
    1.57 @@ -848,16 +863,21 @@
    1.58      SDL_LowerBlit(surface, &bounds, convert, &bounds);
    1.59  
    1.60      /* Clean up the original surface, and update converted surface */
    1.61 -    convert->map->info.r = surface->map->info.r;
    1.62 -    convert->map->info.g = surface->map->info.g;
    1.63 -    convert->map->info.b = surface->map->info.b;
    1.64 -    convert->map->info.a = surface->map->info.a;
    1.65 +    convert->map->info.r = copy_color.r;
    1.66 +    convert->map->info.g = copy_color.g;
    1.67 +    convert->map->info.b = copy_color.b;
    1.68 +    convert->map->info.a = copy_color.a;
    1.69      convert->map->info.flags =
    1.70          (copy_flags &
    1.71           ~(SDL_COPY_COLORKEY | SDL_COPY_BLEND
    1.72             | SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY |
    1.73             SDL_COPY_RLE_ALPHAKEY));
    1.74 +    surface->map->info.r = copy_color.r;
    1.75 +    surface->map->info.g = copy_color.g;
    1.76 +    surface->map->info.b = copy_color.b;
    1.77 +    surface->map->info.a = copy_color.a;
    1.78      surface->map->info.flags = copy_flags;
    1.79 +    SDL_InvalidateMap(surface->map);
    1.80      if (copy_flags & SDL_COPY_COLORKEY) {
    1.81          SDL_bool set_colorkey_by_color = SDL_FALSE;
    1.82