From f48576600538208f96a1b59101c0f73be5ba10e9 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Sun, 23 Feb 2020 23:07:15 +0100 Subject: [PATCH] Fix: set to opaque when a palette surface is converted to an alpha format. --- src/video/SDL_surface.c | 84 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index d10841530a764..2285370f0c334 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -402,6 +402,64 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface, SDL_bool ignore_alpha) SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); } + +static void +SDL_ConvertSetOpaque(SDL_Surface * surface) +{ + int x, y; + + if (!surface) { + return; + } + + if (!surface->format->Amask) { + return; + } + + SDL_LockSurface(surface); + + switch (surface->format->BytesPerPixel) { + case 2: + { + Uint16 *row, *spot; + Uint16 mask = (Uint16) (surface->format->Amask); + + row = (Uint16 *) surface->pixels; + for (y = surface->h; y--;) { + spot = row; + for (x = surface->w; x--;) { + *spot |= mask; + ++spot; + } + row += surface->pitch / 2; + } + } + break; + case 3: + /* FIXME */ + break; + case 4: + { + Uint32 *row, *spot; + Uint32 mask = surface->format->Amask; + + row = (Uint32 *) surface->pixels; + for (y = surface->h; y--;) { + spot = row; + for (x = surface->w; x--;) { + *spot |= mask; + ++spot; + } + row += surface->pitch / 4; + } + } + break; + } + + SDL_UnlockSurface(surface); +} + + int SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g, Uint8 b) { @@ -962,9 +1020,9 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, SDL_Color copy_color; SDL_Rect bounds; int ret; - int palette_ck_transform = 0; + SDL_bool palette_ck_transform = SDL_FALSE; int palette_ck_value = 0; - int palette_has_alpha = SDL_FALSE; + SDL_bool palette_has_alpha = SDL_FALSE; if (!surface) { SDL_InvalidParamError("surface"); @@ -1029,7 +1087,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, /* Transform colorkey to alpha. for cases where source palette has duplicate values, and colorkey is one of them */ if (copy_flags & SDL_COPY_COLORKEY) { if (surface->format->palette && !format->palette) { - palette_ck_transform = 1; + palette_ck_transform = SDL_TRUE; palette_has_alpha = SDL_TRUE; palette_ck_value = surface->format->palette->colors[surface->map->info.colorkey].a; surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT; @@ -1135,6 +1193,26 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, } } + /* Source surface has a palette with no alpha nor colorkey. + * Destination format has alpha. + * We may need to set the alpha channel to opaque. */ + if (surface->format->palette && format->Amask && palette_has_alpha == SDL_FALSE) { + SDL_bool need_opaque = SDL_FALSE; + int i; + for (i = 0; i < surface->format->palette->ncolors; i++) { + Uint8 alpha_value = surface->format->palette->colors[i].a; + if (alpha_value == 0) { + need_opaque = SDL_TRUE; + break; + } + } + + if (need_opaque) { + SDL_ConvertSetOpaque(convert); + } + } + + /* Enable alpha blending by default if the new surface has an * alpha channel or alpha modulation */ if ((surface->format->Amask && format->Amask) ||