From 850d09b0a5d65a53cba6391dea156fb74dfbfbc4 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 2 Oct 2019 22:58:49 +0100 Subject: [PATCH] Minor cleanup of internal error handling 1. TTF no longer crashes on exit. 2. Art failing to load simply isn't rendered instead of crashing in random places. 3. Fixes empty line rendering in ttf_render_wrapped.cpp 4. dx_cleanup is now idempotent. --- SourceX/DiabloUI/art.cpp | 7 +++++-- SourceX/DiabloUI/art.h | 2 +- SourceX/DiabloUI/art_draw.cpp | 2 +- SourceX/DiabloUI/diabloui.cpp | 4 ++++ SourceX/DiabloUI/dialogs.cpp | 11 ++++++++--- SourceX/DiabloUI/dialogs.h | 1 + SourceX/DiabloUI/fonts.cpp | 12 +++++++----- SourceX/DiabloUI/text_draw.cpp | 2 ++ SourceX/DiabloUI/ttf_render_wrapped.cpp | 17 ++++++++++++++--- SourceX/dx.cpp | 3 +++ 10 files changed, 46 insertions(+), 15 deletions(-) diff --git a/SourceX/DiabloUI/art.cpp b/SourceX/DiabloUI/art.cpp index 62a04c220..8f078d17e 100644 --- a/SourceX/DiabloUI/art.cpp +++ b/SourceX/DiabloUI/art.cpp @@ -32,6 +32,7 @@ void LoadArt(const char *pszFile, Art *art, int frames, PALETTEENTRY *pPalette) art_surface->pitch * art_surface->format->BytesPerPixel * height, 0, 0, 0)) { SDL_Log("Failed to load image"); SDL_FreeSurface(art_surface); + art->surface = nullptr; return; } @@ -43,11 +44,13 @@ void LoadArt(const char *pszFile, Art *art, int frames, PALETTEENTRY *pPalette) void LoadMaskedArt(const char *pszFile, Art *art, int frames, int mask) { LoadArt(pszFile, art, frames); + if (art->surface != nullptr) { #ifdef USE_SDL1 - SDL_SetColorKey(art->surface, SDL_SRCCOLORKEY, mask); + SDL_SetColorKey(art->surface, SDL_SRCCOLORKEY, mask); #else - SDL_SetColorKey(art->surface, SDL_TRUE, mask); + SDL_SetColorKey(art->surface, SDL_TRUE, mask); #endif + } } } // namespace dvl diff --git a/SourceX/DiabloUI/art.h b/SourceX/DiabloUI/art.h index 14e13650b..236b7ec45 100644 --- a/SourceX/DiabloUI/art.h +++ b/SourceX/DiabloUI/art.h @@ -12,7 +12,7 @@ struct Art { int w() const { - return surface->w; + return surface ? surface->w : 0; } int h() const diff --git a/SourceX/DiabloUI/art_draw.cpp b/SourceX/DiabloUI/art_draw.cpp index d255a1201..a1f37977d 100644 --- a/SourceX/DiabloUI/art_draw.cpp +++ b/SourceX/DiabloUI/art_draw.cpp @@ -8,7 +8,7 @@ extern unsigned int pal_surface_palette_version; void DrawArt(int screenX, int screenY, Art *art, int nFrame, decltype(SDL_Rect().w) srcW, decltype(SDL_Rect().h) srcH) { - if (screenY >= SCREEN_Y + SCREEN_HEIGHT || screenX >= SCREEN_X + SCREEN_WIDTH) + if (screenY >= SCREEN_Y + SCREEN_HEIGHT || screenX >= SCREEN_X + SCREEN_WIDTH || art->surface == nullptr) return; SDL_Rect src_rect = { diff --git a/SourceX/DiabloUI/diabloui.cpp b/SourceX/DiabloUI/diabloui.cpp index 7d58e498b..d8fc5ccc6 100644 --- a/SourceX/DiabloUI/diabloui.cpp +++ b/SourceX/DiabloUI/diabloui.cpp @@ -12,6 +12,7 @@ #include "DiabloUI/text_draw.h" #include "DiabloUI/fonts.h" #include "DiabloUI/button.h" +#include "DiabloUI/dialogs.h" namespace dvl { @@ -600,6 +601,9 @@ void LoadBackgroundArt(char *pszFile) fadeValue = 0; LoadArt(pszFile, &ArtBackground, 1, pPal); + if (ArtBackground.surface == nullptr) + return; + LoadPalInMem(pPal); ApplyGamma(logical_palette, orig_palette, 256); } diff --git a/SourceX/DiabloUI/dialogs.cpp b/SourceX/DiabloUI/dialogs.cpp index fd0767d1b..a8800550e 100644 --- a/SourceX/DiabloUI/dialogs.cpp +++ b/SourceX/DiabloUI/dialogs.cpp @@ -14,7 +14,7 @@ namespace { Art dialogArt; Art progressArt; char dialogText[256]; -char dialogCaption[256]; +char dialogCaption[1024]; bool fontWasLoaded; bool textInputWasActive; @@ -156,13 +156,18 @@ void DialogLoop(UiItem *items, std::size_t num_items, UiItem *render_behind, std } // namespace -void UiErrorOkDialog(const char *text, const char *caption, UiItem *render_behind, std::size_t render_behind_size) +void UiOkDialog(const char *text, const char *caption, bool error, UiItem *render_behind, std::size_t render_behind_size) { - Init(text, caption, /*error=*/true); + Init(text, caption, error); DialogLoop(dialogItems, dialogItemsSize, render_behind, render_behind_size); Deinit(); } +void UiErrorOkDialog(const char *text, const char *caption, UiItem *render_behind, std::size_t render_behind_size) +{ + UiOkDialog(text, caption, /*error=*/true, render_behind, render_behind_size); +} + void UiErrorOkDialog(const char *text, UiItem *render_behind, std::size_t render_behind_size) { UiErrorOkDialog(text, nullptr, render_behind, render_behind_size); diff --git a/SourceX/DiabloUI/dialogs.h b/SourceX/DiabloUI/dialogs.h index ca1bfd7e6..34ea107b7 100644 --- a/SourceX/DiabloUI/dialogs.h +++ b/SourceX/DiabloUI/dialogs.h @@ -8,5 +8,6 @@ namespace dvl { void UiErrorOkDialog(const char *text, UiItem *renderBehind, std::size_t renderBehindSize); void UiErrorOkDialog(const char *text, const char *caption, UiItem *render_behind, std::size_t render_behind_size); +void UiOkDialog(const char *text, const char *caption, bool error, UiItem *render_behind, std::size_t render_behind_size); } // namespace dvl diff --git a/SourceX/DiabloUI/fonts.cpp b/SourceX/DiabloUI/fonts.cpp index 88bcd409f..42c37d838 100644 --- a/SourceX/DiabloUI/fonts.cpp +++ b/SourceX/DiabloUI/fonts.cpp @@ -50,11 +50,13 @@ void UnloadArtFonts() } void LoadTtfFont() { - if (!TTF_WasInit() && TTF_Init() == -1) { - printf("TTF_Init: %s\n", TTF_GetError()); - exit(1); + if (!TTF_WasInit()) { + if (TTF_Init() == -1) { + printf("TTF_Init: %s\n", TTF_GetError()); + exit(1); + } + atexit(TTF_Quit); } - atexit(TTF_Quit); font = TTF_OpenFont("CharisSILB.ttf", 17); if (font == NULL) { @@ -67,7 +69,7 @@ void LoadTtfFont() { } void UnloadTtfFont() { - if (font) + if (font && TTF_WasInit()) TTF_CloseFont(font); font = nullptr; } diff --git a/SourceX/DiabloUI/text_draw.cpp b/SourceX/DiabloUI/text_draw.cpp index 086a7ea8c..63a6cfd09 100644 --- a/SourceX/DiabloUI/text_draw.cpp +++ b/SourceX/DiabloUI/text_draw.cpp @@ -44,6 +44,8 @@ void DrawTTF(const char *text, const SDL_Rect &rect, int flags, } SDL_Surface *text_surface = (*render_cache)->text; SDL_Surface *shadow_surface = (*render_cache)->shadow; + if (text_surface == nullptr) + return; SDL_Rect dest_rect = rect; const int x_offset = AlignXOffset(flags, rect, text_surface->w); diff --git a/SourceX/DiabloUI/ttf_render_wrapped.cpp b/SourceX/DiabloUI/ttf_render_wrapped.cpp index b54fab0c8..86c35fff2 100644 --- a/SourceX/DiabloUI/ttf_render_wrapped.cpp +++ b/SourceX/DiabloUI/ttf_render_wrapped.cpp @@ -109,16 +109,16 @@ SDL_Surface *RenderUTF8_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Colo } if (!strLines) { + SDL_stack_free(str); return TTF_RenderUTF8_Solid(font, text, fg); } /* Create the target surface */ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, (numLines > 1) ? wrapLength : width, height * numLines + (lineSpace * (numLines - 1)), 8, 0, 0, 0, 0); if (textbuf == nullptr) { - if (strLines) { + if (strLines) SDL_free(strLines); - SDL_stack_free(str); - } + SDL_stack_free(str); return nullptr; } @@ -141,7 +141,18 @@ SDL_Surface *RenderUTF8_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Colo SDL_Rect dest = { 0, 0, 0, 0 }; for (std::size_t line = 0; line < numLines; line++) { text = strLines[line]; + if (!text || !*text) { + dest.y += lineskip; + continue; + } SDL_Surface *tmp = TTF_RenderUTF8_Solid(font, text, fg); + if (tmp == nullptr) { + SDL_Log(TTF_GetError()); + SDL_FreeSurface(textbuf); + SDL_free(strLines); + SDL_stack_free(str); + return nullptr; + } dest.w = static_cast(tmp->w); dest.h = static_cast(tmp->h); diff --git a/SourceX/dx.cpp b/SourceX/dx.cpp index 176cf7dc3..bb3670e05 100644 --- a/SourceX/dx.cpp +++ b/SourceX/dx.cpp @@ -146,7 +146,10 @@ void dx_cleanup() gpBuffer = NULL; sgMemCrit.Leave(); + if (pal_surface == nullptr) + return; SDL_FreeSurface(pal_surface); + pal_surface = nullptr; SDL_FreePalette(palette); SDL_FreeSurface(surface); SDL_DestroyTexture(texture);