diff --git a/sc2/src/sc2code/comm.c b/sc2/src/sc2code/comm.c index 7b8e22fd7..04b9656ee 100644 --- a/sc2/src/sc2code/comm.c +++ b/sc2/src/sc2code/comm.c @@ -106,6 +106,9 @@ static int subtitle_state = DONE_SUBTITLE; static Mutex subtitle_mutex; int do_subtitles (UNICODE *pStr); +static UNICODE *last_subtitle; +static TFB_Image *subtitle_cache; + /* _count_lines - mostly stolen from add_text, just sees how many lines a given input string would take to display given the line wrapping information */ @@ -172,12 +175,33 @@ add_text (int status, PTEXT pTextIn) UNICODE ch, *pStr; SIZE text_width; int num_lines = 0; - + static COORD last_baseline; + BatchGraphics (); maxchars = (COUNT)~0; if (status == 1) { + RECT r; + GetContextClipRect (&r); + + if (last_subtitle == pTextIn->pStr) + { + // draws cached subtitle + TFB_DrawScreen_Image (subtitle_cache, r.corner.x, r.corner.y, 0, 0, TFB_SCREEN_MAIN); + UnbatchGraphics (); + return last_baseline; + } + else + { + // saves background to extra screen + TFB_DrawScreen_Copy (&r, TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA); + // fills screen with transparent color + TFB_DrawScreen_Rect (&r, 0, 0, 255, TFB_SCREEN_MAIN); + + last_subtitle = pTextIn->pStr; + } + text_width = CommData.AlienTextWidth; SetContextFont (CommData.AlienFont); GetContextFontLeading (&leading); @@ -312,6 +336,21 @@ add_text (int status, PTEXT pTextIn) } while ((ch = *pStr++) != '\0' && ch != '\n' && ch != '\r' && maxchars); pText->pStr = pStr; + if (status == 1) + { + RECT r; + GetContextClipRect (&r); + + // copies subtitle to cache + TFB_DrawScreen_CopyToImage (subtitle_cache, &r, TFB_SCREEN_MAIN); + // restores background + TFB_DrawScreen_Copy (&r, TFB_SCREEN_EXTRA, TFB_SCREEN_MAIN); + // draws cached subtitle + TFB_DrawScreen_Image (subtitle_cache, r.corner.x, r.corner.y, 0, 0, TFB_SCREEN_MAIN); + + last_baseline = pText->baseline.y; + } + UnbatchGraphics (); return (pText->baseline.y); } @@ -479,8 +518,14 @@ xform_complete (void) void init_communication (void) { + TFB_Canvas canvas; + subtitle_mutex = CreateMutex (); init_xform_control (); + + canvas = TFB_DrawCanvas_New_TrueColor (ScreenWidth, ScreenHeight, FALSE); + subtitle_cache = TFB_DrawImage_New (canvas); + TFB_DrawCanvas_SetTransparentColor (subtitle_cache->NormalImg, 0, 0, 255, TRUE); } void @@ -488,6 +533,8 @@ uninit_communication (void) { DestroyMutex (subtitle_mutex); uninit_xform_control (); + TFB_DrawImage_Delete (subtitle_cache); + subtitle_cache = NULL; } static BOOLEAN ColorChange; @@ -1997,7 +2044,9 @@ InitCommunication (RESOURCE which_comm) COUNT status; MEM_HANDLE hOldIndex, hIndex; LOCDATAPTR LocDataPtr; - + + last_subtitle = NULL; + SetSemaphore (GraphicsSem); if (LastActivity & CHECK_LOAD) diff --git a/sc2/src/sc2code/libs/graphics/sdl/canvas.c b/sc2/src/sc2code/libs/graphics/sdl/canvas.c index efeb0517a..640ca2f7a 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/canvas.c +++ b/sc2/src/sc2code/libs/graphics/sdl/canvas.c @@ -215,7 +215,7 @@ TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int typ src->format->Bmask, src->format->Amask); if (src->format->palette) - TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src)); + TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src), FALSE); } } else @@ -312,11 +312,20 @@ TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas) } void -TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index) +TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index, BOOLEAN rleaccel) { if (index >= 0) { - SDL_SetColorKey ((SDL_Surface *)canvas, SDL_SRCCOLORKEY, index); + int flags = SDL_SRCCOLORKEY; + if (rleaccel) + flags |= SDL_RLEACCEL; + SDL_SetColorKey ((SDL_Surface *)canvas, flags, index); + + if (!TFB_DrawCanvas_IsPaletted (canvas)) + { + // disables alpha channel so color key transparency actually works + SDL_SetAlpha ((SDL_Surface *)canvas, 0, 255); + } } else { @@ -324,6 +333,21 @@ TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index) } } +void +TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOLEAN rleaccel) +{ + int flags = SDL_SRCCOLORKEY; + if (rleaccel) + flags |= SDL_RLEACCEL; + SDL_SetColorKey ((SDL_Surface *)canvas, flags, SDL_MapRGB (((SDL_Surface *)canvas)->format, r, g, b)); + + if (!TFB_DrawCanvas_IsPaletted (canvas)) + { + // disables alpha channel so color key transparency actually works + SDL_SetAlpha ((SDL_Surface *)canvas, 0, 255); + } +} + void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, TFB_Canvas src_mipmap, int scale, PEXTENT size) { diff --git a/sc2/src/sc2code/libs/graphics/tfb_draw.h b/sc2/src/sc2code/libs/graphics/tfb_draw.h index 196ebe920..7b1f2c46e 100644 --- a/sc2/src/sc2code/libs/graphics/tfb_draw.h +++ b/sc2/src/sc2code/libs/graphics/tfb_draw.h @@ -99,7 +99,8 @@ void TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, TFB_Palette *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas); void TFB_DrawCanvas_SetPalette (TFB_Canvas target, TFB_Palette *palette); int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas); -void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int i); +void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int i, BOOLEAN rleaccel); +void TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOLEAN rleaccel); void TFB_DrawCanvas_Initialize (void); #endif diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c index a39dee2ac..92824d01b 100644 --- a/sc2/src/starcon2.c +++ b/sc2/src/starcon2.c @@ -327,9 +327,9 @@ main (int argc, char *argv[]) GraphicsSem = CreateSemaphore (1, "Graphics"); RenderingCond = CreateCondVar (); - init_communication (); TFB_InitGraphics (gfxdriver, gfxflags, width, height, bpp); + init_communication (); if (gammaset) TFB_SetGamma (gamma); TFB_InitSound (snddriver, soundflags);