Fixed bug 3827 - issue with MapRGB, palette and colorkey

For a palettized surface, prevent SDL_MapRGB() value to change whether colorkey is set or not.
Sylvain Becker 2019-01-21 18:45:15 +01:00
parent 07548602d6
commit 2bd26b8da8
1 changed files with 54 additions and 38 deletions

View File

@ -268,21 +268,7 @@ SDL_SetColorKey(SDL_Surface * surface, int flag, Uint32 key)
if (flag) { if (flag) {
surface->map->info.flags |= SDL_COPY_COLORKEY; surface->map->info.flags |= SDL_COPY_COLORKEY;
surface->map->info.colorkey = key; surface->map->info.colorkey = key;
if (surface->format->palette) {
surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
++surface->format->palette->version;
if (!surface->format->palette->version) {
surface->format->palette->version = 1;
}
}
} else { } else {
if (surface->format->palette) {
surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_OPAQUE;
++surface->format->palette->version;
if (!surface->format->palette->version) {
surface->format->palette->version = 1;
}
}
surface->map->info.flags &= ~SDL_COPY_COLORKEY; surface->map->info.flags &= ~SDL_COPY_COLORKEY;
} }
if (surface->map->info.flags != flags) { if (surface->map->info.flags != flags) {
@ -325,7 +311,7 @@ SDL_GetColorKey(SDL_Surface * surface, Uint32 * key)
/* This is a fairly slow function to switch from colorkey to alpha */ /* This is a fairly slow function to switch from colorkey to alpha */
static void static void
SDL_ConvertColorkeyToAlpha(SDL_Surface * surface) SDL_ConvertColorkeyToAlpha(SDL_Surface * surface, SDL_bool ignore_alpha)
{ {
int x, y; int x, y;
@ -347,7 +333,8 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
Uint16 ckey = (Uint16) surface->map->info.colorkey; Uint16 ckey = (Uint16) surface->map->info.colorkey;
Uint16 mask = (Uint16) (~surface->format->Amask); Uint16 mask = (Uint16) (~surface->format->Amask);
/* Ignore alpha in colorkey comparison */ /* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask; ckey &= mask;
row = (Uint16 *) surface->pixels; row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) { for (y = surface->h; y--;) {
@ -360,6 +347,19 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
} }
row += surface->pitch / 2; row += surface->pitch / 2;
} }
} else {
row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
++spot;
}
row += surface->pitch / 2;
}
}
} }
break; break;
case 3: case 3:
@ -371,7 +371,8 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
Uint32 ckey = surface->map->info.colorkey; Uint32 ckey = surface->map->info.colorkey;
Uint32 mask = ~surface->format->Amask; Uint32 mask = ~surface->format->Amask;
/* Ignore alpha in colorkey comparison */ /* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask; ckey &= mask;
row = (Uint32 *) surface->pixels; row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) { for (y = surface->h; y--;) {
@ -384,6 +385,19 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
} }
row += surface->pitch / 4; row += surface->pitch / 4;
} }
} else {
row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
++spot;
}
row += surface->pitch / 4;
}
}
} }
break; break;
} }
@ -1023,6 +1037,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_InvalidateMap(surface->map); SDL_InvalidateMap(surface->map);
if (copy_flags & SDL_COPY_COLORKEY) { if (copy_flags & SDL_COPY_COLORKEY) {
SDL_bool set_colorkey_by_color = SDL_FALSE; SDL_bool set_colorkey_by_color = SDL_FALSE;
SDL_bool ignore_alpha = SDL_TRUE; /* Ignore, or not, alpha in colorkey comparison */
if (surface->format->palette) { if (surface->format->palette) {
if (format->palette && if (format->palette &&
@ -1032,7 +1047,8 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
/* The palette is identical, just set the same colorkey */ /* The palette is identical, just set the same colorkey */
SDL_SetColorKey(convert, 1, surface->map->info.colorkey); SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
} else if (format->Amask) { } else if (format->Amask) {
/* The alpha was set in the destination from the palette */ set_colorkey_by_color = SDL_TRUE;
ignore_alpha = SDL_FALSE;
} else { } else {
set_colorkey_by_color = SDL_TRUE; set_colorkey_by_color = SDL_TRUE;
} }
@ -1073,7 +1089,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_SetColorKey(convert, 1, converted_colorkey); SDL_SetColorKey(convert, 1, converted_colorkey);
/* This is needed when converting for 3D texture upload */ /* This is needed when converting for 3D texture upload */
SDL_ConvertColorkeyToAlpha(convert); SDL_ConvertColorkeyToAlpha(convert, ignore_alpha);
} }
} }
SDL_SetClipRect(convert, &surface->clip_rect); SDL_SetClipRect(convert, &surface->clip_rect);