diff --git a/Source/engine/render/pcx_render.cpp b/Source/engine/render/pcx_render.cpp index 9c7f0f00c..16411722a 100644 --- a/Source/engine/render/pcx_render.cpp +++ b/Source/engine/render/pcx_render.cpp @@ -28,6 +28,8 @@ const uint8_t *SkipRestOfPcxLine(const uint8_t *src, unsigned remainingWidth) template void BlitPcxClipY(const Surface &out, Point position, const uint8_t *src, unsigned srcWidth, unsigned srcHeight, const uint8_t *colorMap, uint8_t transparentColor) { + if (position.y >= out.h()) + return; while (position.y < 0 && srcHeight != 0) { src = SkipRestOfPcxLine(src, srcWidth); ++position.y; @@ -42,17 +44,16 @@ void BlitPcxClipY(const Surface &out, Point position, const uint8_t *src, unsign for (unsigned x = 0; x < srcWidth;) { const uint8_t value = *src++; if (value <= PcxMaxSinglePixel) { - const uint8_t color = UseColorMap ? colorMap[value] : value; - if (!(HasTransparency && color == transparentColor)) { - *dst = color; + if (!(HasTransparency && value == transparentColor)) { + *dst = UseColorMap ? colorMap[value] : value; } ++dst; ++x; } else { const uint8_t runLength = value & PcxRunLengthMask; - const uint8_t color = UseColorMap ? colorMap[*src++] : *src++; + const uint8_t color = *src++; if (!(HasTransparency && color == transparentColor)) { - std::memset(dst, color, runLength); + std::memset(dst, UseColorMap ? colorMap[color] : color, runLength); } dst += runLength; x += runLength; @@ -66,6 +67,8 @@ void BlitPcxClipY(const Surface &out, Point position, const uint8_t *src, unsign template void BlitPcxClipXY(const Surface &out, Point position, const uint8_t *src, unsigned srcWidth, unsigned srcHeight, ClipX clipX, const uint8_t *colorMap, uint8_t transparentColor) { + if (position.y >= out.h() || position.x >= out.w()) + return; while (position.y < 0 && srcHeight != 0) { src = SkipRestOfPcxLine(src, srcWidth); ++position.y; @@ -91,15 +94,16 @@ void BlitPcxClipXY(const Surface &out, Point position, const uint8_t *src, unsig const uint8_t runLength = value & PcxRunLengthMask; if (runLength > remainingLeftClip) { const uint8_t overshoot = runLength - remainingLeftClip; - const uint8_t color = UseColorMap ? colorMap[*src++] : *src++; + const uint8_t originalColor = *src++; + const uint8_t color = UseColorMap ? colorMap[originalColor] : originalColor; if (overshoot > remainingWidth) { - if (!(HasTransparency && color == transparentColor)) { + if (!(HasTransparency && originalColor == transparentColor)) { std::memset(dst, color, remainingWidth); } dst += remainingWidth; remainingWidth = 0; } else { - if (!(HasTransparency && color == transparentColor)) { + if (!(HasTransparency && originalColor == transparentColor)) { std::memset(dst, color, overshoot); } dst += overshoot; @@ -107,33 +111,35 @@ void BlitPcxClipXY(const Surface &out, Point position, const uint8_t *src, unsig } remainingLeftClip = 0; break; - } else { - ++src; - remainingLeftClip -= runLength; } + ++src; + remainingLeftClip -= runLength; } } while (remainingWidth > 0) { const uint8_t value = *src++; if (value <= PcxMaxSinglePixel) { - *dst++ = UseColorMap ? colorMap[value] : value; + if (!(HasTransparency && value == transparentColor)) { + *dst = UseColorMap ? colorMap[value] : value; + } + ++dst; --remainingWidth; continue; } const uint8_t runLength = value & PcxRunLengthMask; - const uint8_t color = UseColorMap ? colorMap[*src++] : *src++; + const uint8_t originalColor = *src++; + const uint8_t color = UseColorMap ? colorMap[originalColor] : originalColor; if (runLength > remainingWidth) { - if (!(HasTransparency && color == transparentColor)) { + if (!(HasTransparency && originalColor == transparentColor)) { std::memset(dst, color, remainingWidth); } dst += remainingWidth; remainingWidth -= runLength; break; - } else { - if (!(HasTransparency && color == transparentColor)) { - std::memset(dst, color, runLength); - } + } + if (!(HasTransparency && originalColor == transparentColor)) { + std::memset(dst, color, runLength); } dst += runLength; remainingWidth -= runLength; diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index d89da7992..b7f2f1acc 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -17,9 +17,10 @@ #include "engine.h" #include "engine/load_cel.hpp" #include "engine/load_file.hpp" -#include "engine/load_pcx_as_cel.hpp" +#include "engine/load_pcx.hpp" #include "engine/point.hpp" #include "palette.h" +#include "pcx_render.hpp" #include "utils/display.h" #include "utils/language.h" #include "utils/sdl_compat.h" @@ -34,8 +35,8 @@ namespace { constexpr char32_t ZWSP = U'\u200B'; // Zero-width space -using Font = const OwnedCelSpriteWithFrameHeight; -std::unordered_map> Fonts; +using Font = const OwnedPcxSpriteSheet; +std::unordered_map> Fonts; std::unordered_map> FontKerns; std::array FontSizes = { 12, 24, 30, 42, 46, 22 }; @@ -66,6 +67,8 @@ std::array ColorTranslations = { "fonts\\buttonpushed.trn", }; +std::array>, 14> ColorTranslationsData; + GameFontTables GetSizeFromFlags(UiFlags flags) { if (HasAnyOf(flags, UiFlags::FontSize24)) @@ -166,9 +169,9 @@ std::array *LoadFontKerning(GameFontTables size, uint16_t row) return kerning; } -uint32_t GetFontId(GameFontTables size, text_color color, uint16_t row) +uint32_t GetFontId(GameFontTables size, uint16_t row) { - return (color << 24) | (size << 16) | row; + return (size << 16) | row; } void GetFontPath(GameFontTables size, uint16_t row, char *out) @@ -176,10 +179,14 @@ void GetFontPath(GameFontTables size, uint16_t row, char *out) sprintf(out, "fonts\\%i-%02x.pcx", FontSizes[size], row); } -const OwnedCelSpriteWithFrameHeight *LoadFont(GameFontTables size, text_color color, uint16_t row) +const OwnedPcxSpriteSheet *LoadFont(GameFontTables size, text_color color, uint16_t row) { - const uint32_t fontId = GetFontId(size, color, row); + if (ColorTranslations[color] != nullptr && !ColorTranslationsData[color]) { + ColorTranslationsData[color].emplace(); + LoadFileInMem(ColorTranslations[color], *ColorTranslationsData[color]); + } + const uint32_t fontId = GetFontId(size, row); auto hotFont = Fonts.find(fontId); if (hotFont != Fonts.end()) { return &*hotFont->second; @@ -188,26 +195,25 @@ const OwnedCelSpriteWithFrameHeight *LoadFont(GameFontTables size, text_color co char path[32]; GetFontPath(size, row, &path[0]); - std::optional &font = Fonts[fontId]; + std::optional &font = Fonts[fontId]; constexpr unsigned NumFrames = 256; - font = LoadPcxAssetAsCel(path, NumFrames); + font = LoadPcxSpriteSheetAsset(path, NumFrames, /*transparentColor=*/1); if (!font) { LogError("Error loading font: {}", path); return nullptr; } - if (ColorTranslations[color] != nullptr) { - std::array colorMapping; - LoadFileInMem(ColorTranslations[color], colorMapping); - CelApplyTrans(font->sprite.MutableData(), colorMapping); - } - return &(*font); } -void DrawFont(const Surface &out, Point position, const OwnedCelSpriteWithFrameHeight *font, int frame) +void DrawFont(const Surface &out, Point position, const OwnedPcxSpriteSheet *font, text_color color, int frame) { - CelDrawTo(out, { position.x, static_cast(position.y + font->frameHeight) }, CelSprite { font->sprite }, frame); + PcxSprite glyph = PcxSpriteSheet { *font }.sprite(frame); + if (ColorTranslationsData[color]) { + RenderPcxSpriteWithColorMap(out, glyph, position, *ColorTranslationsData[color]); + } else { + RenderPcxSprite(out, glyph, position); + } } bool IsWhitespace(char32_t c) @@ -387,7 +393,7 @@ int DoDrawString(const Surface &out, string_view text, Rectangle rect, Point &ch continue; } - DrawFont(out, characterPosition, font, frame); + DrawFont(out, characterPosition, font, color, frame); characterPosition.x += (*kerning)[frame] + spacing; } return text.data() - remaining.data(); @@ -646,7 +652,7 @@ uint32_t DrawString(const Surface &out, string_view text, const Rectangle &rect, if (HasAnyOf(flags, UiFlags::PentaCursor)) { CelDrawTo(out, characterPosition + Displacement { 0, lineHeight - BaseLineOffset[size] }, *pSPentSpn2Cels, PentSpn2Spin()); } else if (HasAnyOf(flags, UiFlags::TextCursor) && GetAnimationFrame(2, 500) != 0) { - DrawFont(out, characterPosition, LoadFont(size, color, 0), '|'); + DrawFont(out, characterPosition, LoadFont(size, color, 0), color, '|'); } return bytesDrawn; @@ -746,7 +752,7 @@ void DrawStringWithColors(const Surface &out, string_view fmt, DrawStringFormatA } } - DrawFont(out, characterPosition, font, frame); + DrawFont(out, characterPosition, font, color, frame); characterPosition.x += (*kerning)[frame] + spacing; prev = next; } @@ -754,7 +760,7 @@ void DrawStringWithColors(const Surface &out, string_view fmt, DrawStringFormatA if (HasAnyOf(flags, UiFlags::PentaCursor)) { CelDrawTo(out, characterPosition + Displacement { 0, lineHeight - BaseLineOffset[size] }, *pSPentSpn2Cels, PentSpn2Spin()); } else if (HasAnyOf(flags, UiFlags::TextCursor) && GetAnimationFrame(2, 500) != 0) { - DrawFont(out, characterPosition, LoadFont(size, color, 0), '|'); + DrawFont(out, characterPosition, LoadFont(size, color, 0), color, '|'); } }