From 49f8e058bd6088d4fd29e14ae787c5abbb3b0ee2 Mon Sep 17 00:00:00 2001 From: avolkov Date: Mon, 14 Feb 2005 10:27:12 +0000 Subject: [PATCH] Misc gfx fixes: Better .ani transparency spec (bug #128); Reliable surface transparency in OpenGL mode; Colorkey transparency handling in 32bpp trilinear; --meleescale=nearest fixed (bug #126) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1536 8092fc87-c524-0410-9efc-e669fe64eaf9 --- .../sc2code/libs/graphics/sdl/3do_getbody.c | 18 +++++- sc2/src/sc2code/libs/graphics/sdl/canvas.c | 64 +++++++++++++++---- sc2/src/sc2code/libs/graphics/sdl/opengl.c | 15 +++-- sc2/src/sc2code/libs/graphics/tfb_draw.c | 8 --- 4 files changed, 78 insertions(+), 27 deletions(-) diff --git a/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c b/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c index ba0d5ff74..7350c9676 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c +++ b/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c @@ -50,10 +50,24 @@ process_image (FRAMEPTR FramePtr, SDL_Surface *img[], AniData *ani, int cel_ct) TYPE_SET (FramePtr->TypeIndexAndFlags, ROM_DRAWABLE); INDEX_SET (FramePtr->TypeIndexAndFlags, cel_ct); + // handle transparency cases if (img[cel_ct]->format->palette) - { + { // indexed color image if (ani[cel_ct].transparent_color != -1) - SDL_SetColorKey(img[cel_ct], SDL_SRCCOLORKEY, ani[cel_ct].transparent_color); + SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY, + ani[cel_ct].transparent_color); + } + else if (img[cel_ct]->format->BitsPerPixel > 8) + { // special transparency cases for truecolor images + if (ani[cel_ct].transparent_color == 0) + // make RGB=0,0,0 transparent + SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY, + SDL_MapRGB (img[cel_ct]->format, 0, 0, 0)); + } + if (ani[cel_ct].transparent_color == -1) + { // enforce -1 to mean 'no transparency' + SDL_SetColorKey (img[cel_ct], 0, 0); + // set transparent_color == -2 to use PNG tRNS transparency } hx = ani[cel_ct].hotspot_x; diff --git a/sc2/src/sc2code/libs/graphics/sdl/canvas.c b/sc2/src/sc2code/libs/graphics/sdl/canvas.c index 359d4d8bd..b137ea89a 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/canvas.c +++ b/sc2/src/sc2code/libs/graphics/sdl/canvas.c @@ -474,13 +474,14 @@ TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, PEXTENT size) void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT size) { +#define NNS_MAX_DIMS 600 SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *dst = (SDL_Surface *)dest_canvas; int x, y, sx, sy, *csax, *csay, csx, csy; - int saspace[602]; + int saspace[NNS_MAX_DIMS]; int *sax, *say; - if (size.width + size.height > 600) + if (size.width + size.height > NNS_MAX_DIMS) { fprintf (stderr, "TFB_DrawCanvas_Scale: Tried to zoom an image to unreasonable size! Failing.\n"); return; @@ -492,25 +493,28 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E return; } - sx = (int) (65536.0 * (float) src->w / (float) size.width); - sy = (int) (65536.0 * (float) src->h / (float) size.height); + sx = sy = 0; + if (size.width > 1) + sx = 65536 * (src->w - 1) / (size.width - 1); + if (size.height > 1) + sy = 65536 * (src->h - 1) / (size.height - 1); sax = saspace; - say = saspace + size.width + 1; + say = saspace + size.width; /* * Precalculate row increments + * We start with a value in 0..0.5 range to shift the bigger + * jumps towards the center of the image */ - csx = 0; csax = sax; - for (x = 0; x <= size.width; x++) { + for (x = 0, csx = 0x6000; x < size.width; x++) { *csax = csx >> 16; csax++; csx &= 0xffff; csx += sx; } - csy = 0; csay = say; - for (y = 0; y <= size.height; y++) { + for (y = 0, csy = 0x6000; y < size.height; y++) { *csay = csy >> 16; csay++; csy &= 0xffff; @@ -529,17 +533,17 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E csay = say; for (y = 0; y < size.height; ++y) { + csp += (*csay) * src->pitch; sp = csp; dp = cdp; csax = sax; for (x = 0; x < size.width; ++x) { + sp += *csax; *dp = *sp; ++csax; - sp += *csax; ++dp; } ++csay; - csp += (*csay) * src->pitch; cdp += dst->pitch; } } @@ -556,17 +560,17 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E csay = say; for (y = 0; y < size.height; ++y) { + csp += (*csay) * sgap; sp = csp; dp = cdp; csax = sax; for (x = 0; x < size.width; ++x) { + sp += *csax; *dp = *sp; ++csax; - sp += *csax; ++dp; } ++csay; - csp += (*csay) * sgap; cdp += dgap; } } @@ -804,6 +808,14 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, int fsy1 = (int)(65536.0f * (float)mipmap->h / h); int sx0 = 0, sy0 = 0, sx1 = 0, sy1 = 0; int x, y; + Uint32 ck0 = 0; // 0 means alpha=0 too, so it's safe + Uint32 ck1 = 0; + + // use colorkeys where appropriate + if (src->flags & SDL_SRCCOLORKEY) + ck0 = src->format->colorkey; + if (mipmap->flags & SDL_SRCCOLORKEY) + ck1 = mipmap->format->colorkey; SDL_LockSurface(src); SDL_LockSurface(dst); @@ -839,10 +851,19 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, { SDL_GetRGBA (*src_p0, src->format, &r0[0], &g0[0], &b0[0], &a0[0]); SDL_GetRGBA (*(src_p0 + 1), src->format, &r0[1], &g0[1], &b0[1], &a0[1]); + if (src_p0[0] == ck0) + a0[0] = 0; + if (src_p0[1] == ck0) + a0[1] = 0; + if ((sy0 >> 16) <= src->h - 2) { SDL_GetRGBA (*(src_p0 + src->w), src->format, &r0[2], &g0[2], &b0[2], &a0[2]); SDL_GetRGBA (*(src_p0 + src->w + 1), src->format, &r0[3], &g0[3], &b0[3], &a0[3]); + if (src_p0[src->w] == ck0) + a0[2] = 0; + if (src_p0[src->w + 1] == ck0) + a0[3] = 0; } else { @@ -859,6 +880,8 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, else { SDL_GetRGBA (*src_p0, src->format, &r0[0], &g0[0], &b0[0], &a0[0]); + if (src_p0[0] == ck0) + a0[0] = 0; r0[1] = r0[0]; g0[1] = g0[0]; b0[1] = b0[0]; @@ -866,6 +889,8 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, if ((sy0 >> 16) <= src->h - 2) { SDL_GetRGBA (*(src_p0 + src->w), src->format, &r0[2], &g0[2], &b0[2], &a0[2]); + if (src_p0[src->w] == ck0) + a0[2] = 0; r0[3] = r0[2]; g0[3] = g0[2]; b0[3] = b0[2]; @@ -884,10 +909,19 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, { SDL_GetRGBA (*src_p1, mipmap->format, &r1[0], &g1[0], &b1[0], &a1[0]); SDL_GetRGBA (*(src_p1 + 1), mipmap->format, &r1[1], &g1[1], &b1[1], &a1[1]); + if (src_p1[0] == ck1) + a1[0] = 0; + if (src_p1[1] == ck1) + a1[1] = 0; + if ((sy1 >> 16) <= mipmap->h - 2) { SDL_GetRGBA (*(src_p1 + mipmap->w) , mipmap->format, &r1[2], &g1[2], &b1[2], &a1[2]); SDL_GetRGBA (*(src_p1 + mipmap->w + 1), mipmap->format, &r1[3], &g1[3], &b1[3], &a1[3]); + if (src_p1[mipmap->w] == ck1) + a1[2] = 0; + if (src_p1[mipmap->w + 1] == ck1) + a1[3] = 0; } else { @@ -904,6 +938,8 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, else { SDL_GetRGBA (*src_p1, mipmap->format, &r1[0], &g1[0], &b1[0], &a1[0]); + if (src_p1[0] == ck1) + a1[0] = 0; r1[1] = r1[0]; g1[1] = g1[0]; b1[1] = b1[0]; @@ -911,6 +947,8 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, if ((sy1 >> 16) <= mipmap->h - 2) { SDL_GetRGBA (*(src_p1 + mipmap->w), mipmap->format, &r1[2], &g1[2], &b1[2], &a1[2]); + if (src_p1[mipmap->w] == ck1) + a1[2] = 0; r1[3] = r1[2]; g1[3] = g1[2]; b1[3] = b1[2]; diff --git a/sc2/src/sc2code/libs/graphics/sdl/opengl.c b/sc2/src/sc2code/libs/graphics/sdl/opengl.c index 6faa18c18..bb7e22ffd 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/opengl.c +++ b/sc2/src/sc2code/libs/graphics/sdl/opengl.c @@ -443,15 +443,22 @@ TFB_GL_SwapBuffers (int force_full_redraw) TFB_GL_ScanLines (); SDL_GL_SwapBuffers (); - - /* remove compiler warning */ - (void) force_full_redraw; } SDL_Surface* TFB_GL_DisplayFormatAlpha (SDL_Surface *surface) { - return SDL_ConvertSurface (surface, format_conv_surf->format, surface->flags); + SDL_Surface* newsurf; + + newsurf = SDL_ConvertSurface (surface, format_conv_surf->format, surface->flags); + // SDL_SRCCOLORKEY and SDL_SRCALPHA cannot work at the same time, + // so we need to disable one of them + if ((surface->flags & SDL_SRCCOLORKEY) && newsurf + && (newsurf->flags & SDL_SRCCOLORKEY) + && (newsurf->flags & SDL_SRCALPHA)) + SDL_SetAlpha (newsurf, 0, 255); + + return newsurf; } #endif diff --git a/sc2/src/sc2code/libs/graphics/tfb_draw.c b/sc2/src/sc2code/libs/graphics/tfb_draw.c index 4617d1b67..ca26bdb9f 100644 --- a/sc2/src/sc2code/libs/graphics/tfb_draw.c +++ b/sc2/src/sc2code/libs/graphics/tfb_draw.c @@ -331,7 +331,6 @@ TFB_DrawImage_New_Rotated (TFB_Image *img, int angle) TFB_Canvas dst; EXTENT size; TFB_Image* newimg; - int r, g, b; /* sanity check */ if (!img->NormalImg) @@ -352,13 +351,6 @@ TFB_DrawImage_New_Rotated (TFB_Image *img, int angle) TFB_DrawCanvas_Rotate (img->NormalImg, dst, angle, size); newimg = TFB_DrawImage_New (dst); - if (newimg && TFB_DrawCanvas_GetTransparentColor ( - newimg->NormalImg, &r, &g, &b)) - { /* reset colorkey info to clear potential SRCALPHA */ - TFB_DrawCanvas_SetTransparentColor (newimg->NormalImg, - r, g, b, FALSE); - } - return newimg; }