diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 1583510f1..345a41043 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -110,7 +110,6 @@ set(libdevilutionx_SRCS engine/trn.cpp engine/render/automap_render.cpp - engine/render/cel_render.cpp engine/render/cl2_render.cpp engine/render/dun_render.cpp engine/render/pcx_render.cpp diff --git a/Source/engine/load_cel.cpp b/Source/engine/load_cel.cpp index 7a1de7cb6..e567cca55 100644 --- a/Source/engine/load_cel.cpp +++ b/Source/engine/load_cel.cpp @@ -10,16 +10,6 @@ namespace devilution { -OwnedCelSprite LoadCel(const char *pszName, uint16_t width) -{ - return OwnedCelSprite(LoadFileInMem(pszName), width); -} - -OwnedCelSprite LoadCel(const char *pszName, const uint16_t *widths) -{ - return OwnedCelSprite(LoadFileInMem(pszName), widths); -} - OwnedCelSprite LoadCelAsCl2(const char *pszName, uint16_t width) { size_t size; diff --git a/Source/engine/load_cel.hpp b/Source/engine/load_cel.hpp index 5e7f9e77a..7b2ed8abb 100644 --- a/Source/engine/load_cel.hpp +++ b/Source/engine/load_cel.hpp @@ -6,12 +6,6 @@ namespace devilution { -/** - * @brief Loads a Cel sprite and sets its width - */ -OwnedCelSprite LoadCel(const char *pszName, uint16_t width); -OwnedCelSprite LoadCel(const char *pszName, const uint16_t *widths); - OwnedCelSprite LoadCelAsCl2(const char *pszName, uint16_t width); OwnedCelSprite LoadCelAsCl2(const char *pszName, const uint16_t *widths); diff --git a/Source/engine/render/cel_render.cpp b/Source/engine/render/cel_render.cpp deleted file mode 100644 index 0a8ac1f86..000000000 --- a/Source/engine/render/cel_render.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/** - * @file cel_render.cpp - * - * CEL rendering. - */ -#include "engine/render/cel_render.hpp" - -#include -#include - -#include "engine/cel_header.hpp" -#include "engine/palette.h" -#include "engine/render/common_impl.h" -#include "engine/render/scrollrt.h" -#include "engine/trn.hpp" -#include "options.h" -#include "utils/attributes.h" - -namespace devilution { - -namespace { - -constexpr bool IsCelTransparent(uint8_t control) -{ - constexpr uint8_t CelTransparentMin = 0x80; - return control >= CelTransparentMin; -} - -constexpr uint8_t GetCelTransparentWidth(uint8_t control) -{ - return -static_cast(control); -} - -DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT BlitCommand CelGetBlitCommand(const uint8_t *src) -{ - const uint8_t control = *src++; - if (IsCelTransparent(control)) - return BlitCommand { BlitType::Transparent, src, GetCelTransparentWidth(control), 0 }; - return BlitCommand { BlitType::Pixels, src + control, control, 0 }; -} - -template -uint8_t *RenderCelOutlinePixelsCheckFirstColumn( - uint8_t *dst, int dstPitch, int dstX, - const uint8_t *src, uint8_t width, uint8_t color) -{ - if (dstX == -1) { - RenderOutlineForPixel( - dst++, dstPitch, *src++, color); - --width; - } - if (width > 0) { - RenderOutlineForPixel(dst++, dstPitch, *src++, color); - --width; - } - if (width > 0) { - RenderOutlineForPixels(dst, dstPitch, width, src, color); - dst += width; - } - return dst; -} - -template -uint8_t *RenderCelOutlinePixelsCheckLastColumn( - uint8_t *dst, int dstPitch, int dstX, int dstW, - const uint8_t *src, uint8_t width, uint8_t color) -{ - const bool lastPixel = dstX < dstW && width >= 1; - const bool oobPixel = dstX + width > dstW; - const int numSpecialPixels = (lastPixel ? 1 : 0) + (oobPixel ? 1 : 0); - if (width > numSpecialPixels) { - width -= numSpecialPixels; - RenderOutlineForPixels(dst, dstPitch, width, src, color); - src += width; - dst += width; - } - if (lastPixel) - RenderOutlineForPixel(dst++, dstPitch, *src++, color); - if (oobPixel) - RenderOutlineForPixel(dst++, dstPitch, *src++, color); - return dst; -} - -template -uint8_t *RenderCelOutlinePixels( - uint8_t *dst, int dstPitch, int dstX, int dstW, - const uint8_t *src, uint8_t width, uint8_t color) -{ - if (CheckFirstColumn && dstX <= 0) { - return RenderCelOutlinePixelsCheckFirstColumn( - dst, dstPitch, dstX, src, width, color); - } - if (CheckLastColumn && dstX + width >= dstW) { - return RenderCelOutlinePixelsCheckLastColumn( - dst, dstPitch, dstX, dstW, src, width, color); - } - RenderOutlineForPixels(dst, dstPitch, width, src, color); - return dst + width; -} - -template -const uint8_t *RenderCelOutlineRowClipped( // NOLINT(readability-function-cognitive-complexity,misc-no-recursion) - const Surface &out, Point position, const uint8_t *src, ClipX clipX, uint8_t color) -{ - int_fast16_t remainingWidth = clipX.width; - uint8_t v; - - auto *dst = &out[position]; - const auto dstPitch = out.pitch(); - const auto dstW = out.w(); - - if (ClipWidth) { - auto remainingLeftClip = clipX.left; - while (remainingLeftClip > 0) { - v = static_cast(*src++); - if (!IsCelTransparent(v)) { - if (v > remainingLeftClip) { - RenderCelOutlinePixels( - dst, dstPitch, position.x, dstW, src, v - remainingLeftClip, color); - } - src += v; - } else { - v = GetCelTransparentWidth(v); - } - remainingLeftClip -= v; - } - dst -= static_cast(remainingLeftClip); - position.x -= static_cast(remainingLeftClip); - remainingWidth += remainingLeftClip; - } - - while (remainingWidth > 0) { - v = static_cast(*src++); - if (!IsCelTransparent(v)) { - dst = RenderCelOutlinePixels( - dst, dstPitch, position.x, dstW, src, - std::min(remainingWidth, static_cast(v)), color); - src += v; - } else { - v = GetCelTransparentWidth(v); - dst += v; - } - remainingWidth -= v; - position.x += v; - } - - src = SkipRestOfLine(src, clipX.right + remainingWidth); - - return src; -} - -template -void RenderCelOutlineClippedY(const Surface &out, Point position, RenderSrcBackwards src, uint8_t color) // NOLINT(readability-function-cognitive-complexity) -{ - // Skip the bottom clipped lines. - const auto dstHeight = out.h(); - SkipLinesForRenderBackwards(position, src, dstHeight); - if (src.begin == src.end) - return; - - const ClipX clipX = { 0, 0, static_cast(src.width) }; - - if (position.y == dstHeight) { - // After-bottom line - can only draw north. - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - if (src.begin == src.end) - return; - - if (position.y + 1 == dstHeight) { - // Bottom line - cannot draw south. - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - - while (position.y > 0 && src.begin != src.end) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - if (src.begin == src.end) - return; - - if (position.y == 0) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - if (src.begin == src.end) - return; - - if (position.y == -1) { - // Special case: the top of the sprite is 1px below the last line, render just the outline above. - RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } -} - -template -void RenderCelOutlineClippedXY(const Surface &out, Point position, RenderSrcBackwards src, uint8_t color) // NOLINT(readability-function-cognitive-complexity) -{ - // Skip the bottom clipped lines. - const auto dstHeight = out.h(); - SkipLinesForRenderBackwards(position, src, dstHeight); - if (src.begin == src.end) - return; - - ClipX clipX = CalculateClipX(position.x, src.width, out); - if (clipX.width < 0) - return; - if (clipX.left > 0) { - --clipX.left, ++clipX.width; - } else if (clipX.right > 0) { - --clipX.right, ++clipX.width; - } - position.x += static_cast(clipX.left); - - if (position.y == dstHeight) { - // After-bottom line - can only draw north. - if (position.x <= 0) { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } else if (position.x + clipX.width >= out.w()) { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } else { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } - - --position.y; - } - if (src.begin == src.end) - return; - - if (position.y + 1 == dstHeight) { - // Bottom line - cannot draw south. - if (position.x <= 0) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } else if (position.x + clipX.width >= out.w()) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } else { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } - --position.y; - } - - if (position.x <= 0) { - while (position.y > 0 && src.begin != src.end) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - } else if (position.x + clipX.width >= out.w()) { - while (position.y > 0 && src.begin != src.end) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - } else { - while (position.y > 0 && src.begin != src.end) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - --position.y; - } - } - if (src.begin == src.end) - return; - - if (position.y == 0) { - if (position.x <= 0) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } else if (position.x + clipX.width >= out.w()) { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } else { - src.begin = RenderCelOutlineRowClipped( - out, position, src.begin, clipX, color); - } - --position.y; - } - if (src.begin == src.end) - return; - - if (position.y == -1) { - // After-bottom line - can only draw south. - if (position.x <= 0) { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } else if (position.x + clipX.width >= out.w()) { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } else { - src.begin = RenderCelOutlineRowClipped(out, position, src.begin, clipX, color); - } - } -} - -template -void RenderCelOutline(const Surface &out, Point position, const uint8_t *src, std::size_t srcSize, - std::size_t srcWidth, uint8_t color) -{ - RenderSrcBackwards srcForBackwards { src, src + srcSize, static_cast(srcWidth) }; - if (position.x > 0 && position.x + static_cast(srcWidth) < static_cast(out.w())) { - RenderCelOutlineClippedY(out, position, srcForBackwards, color); - } else { - RenderCelOutlineClippedXY(out, position, srcForBackwards, color); - } -} - -/** - * @brief Blit CEL sprite to the given buffer, checks for drawing outside the buffer. - * @param out Target buffer - * @param position Target buffer coordinate - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite in pixels - */ -void CelBlitSafeTo(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth) -{ - assert(pRLEBytes != nullptr); - DoRenderBackwards( - out, position, reinterpret_cast(pRLEBytes), nDataSize, nWidth, BlitDirect {}); -} - -/** - * @brief Same as CelBlitLightSafe, with blended transparency applied - * @param out Target buffer - * @param position Target buffer coordinate - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite in pixels - * @param tbl Palette translation table - */ -void CelBlitLightBlendedSafeTo(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth, const uint8_t *tbl) -{ - assert(pRLEBytes != nullptr); - if (tbl == nullptr) - tbl = &LightTables[LightTableIndex * 256]; - - DoRenderBackwards( - out, position, reinterpret_cast(pRLEBytes), nDataSize, nWidth, BlitBlendedWithMap { tbl }); -} - -void RenderCelWithLightTable(const Surface &out, Point position, const byte *src, std::size_t srcSize, std::size_t srcWidth, const uint8_t *tbl) -{ - DoRenderBackwards( - out, position, reinterpret_cast(src), srcSize, srcWidth, BlitWithMap { tbl }); -} - -/** - * @brief Blit CEL sprite, and apply lighting, to the given buffer, checks for drawing outside the buffer - * @param out Target buffer - * @param position Target buffer coordinate - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite in pixels - * @param tbl Palette translation table - */ -void CelBlitLightSafeTo(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t *tbl) -{ - assert(pRLEBytes != nullptr); - if (tbl == nullptr) - tbl = &LightTables[LightTableIndex * 256]; - RenderCelWithLightTable(out, position, pRLEBytes, nDataSize, nWidth, tbl); -} - -} // namespace - -void CelDrawTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int nDataSize; - const auto *pRLEBytes = CelGetFrame(cel.Data(), frame, &nDataSize); - CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); -} - -void CelClippedDrawTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int nDataSize; - const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); - - CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); -} - -void CelDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame, uint8_t *tbl) -{ - int nDataSize; - const auto *pRLEBytes = CelGetFrame(cel.Data(), frame, &nDataSize); - - if (LightTableIndex != 0 || tbl != nullptr) - CelBlitLightSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame), tbl); - else - CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); -} - -void CelClippedDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int nDataSize; - const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); - - if (LightTableIndex != 0) - CelBlitLightSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame), nullptr); - else - CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); -} - -void CelDrawLightRedTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int nDataSize; - const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); - RenderCelWithLightTable(out, position, pRLEBytes, nDataSize, cel.Width(frame), GetInfravisionTRN()); -} - -void CelDrawItem(const Item &item, const Surface &out, Point position, CelSprite cel, int frame) -{ - bool usable = item._iStatFlag; - if (!usable) { - CelDrawLightRedTo(out, position, cel, frame); - } else { - CelClippedDrawTo(out, position, cel, frame); - } -} - -void CelClippedBlitLightTransTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int nDataSize; - const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); - - if (cel_transparency_active) { - CelBlitLightBlendedSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame), nullptr); - } else if (LightTableIndex != 0) - CelBlitLightSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame), nullptr); - else - CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); -} - -void CelDrawUnsafeTo(const Surface &out, Point position, CelSprite cel, int frame) -{ - int srcSize; - const auto *srcBegin = reinterpret_cast(CelGetFrame(cel.Data(), frame, &srcSize)); - RenderSrcBackwards src { srcBegin, srcBegin + srcSize, cel.Width(frame) }; - DoRenderBackwardsClipY( - out, position, src, BlitDirect {}); -} - -void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, CelSprite cel, int frame, bool skipColorIndexZero) -{ - int nDataSize; - const uint8_t *src = reinterpret_cast(CelGetFrameClipped(cel.Data(), frame, &nDataSize)); - if (skipColorIndexZero) - RenderCelOutline(out, position, src, nDataSize, cel.Width(frame), col); - else - RenderCelOutline(out, position, src, nDataSize, cel.Width(frame), col); -} - -std::pair MeasureSolidHorizontalBounds(CelSprite cel, int frame) -{ - int nDataSize; - const byte *src = CelGetFrameClipped(cel.Data(), frame, &nDataSize); - const auto *end = &src[nDataSize]; - const int celWidth = cel.Width(frame); - - int xBegin = celWidth; - int xEnd = 0; - while (src < end) { - int xCur = 0; - while (xCur < celWidth) { - const auto val = static_cast(*src++); - if (IsCelTransparent(val)) { - const int width = GetCelTransparentWidth(val); - xCur += width; - } else { - xBegin = std::min(xBegin, xCur); - xCur += val; - xEnd = std::max(xEnd, xCur); - src += val; - } - } - if (xBegin == 0 && xEnd == celWidth) - break; - } - return { xBegin, xEnd }; -} - -void CelApplyTrans(byte *p, const std::array &translation) -{ - assert(p != nullptr); - const uint32_t numFrames = LoadLE32(p); - const byte *frameOffsets = p + 4; - p += 4 * (2 + static_cast(numFrames)); - - uint32_t frameEnd = LoadLE32(&frameOffsets[0]); - for (uint32_t i = 0; i < numFrames; ++i) { - const uint32_t frameBegin = frameEnd; - frameEnd = LoadLE32(&frameOffsets[4 * (static_cast(i) + 1)]); - - const byte *end = p + (frameEnd - frameBegin); - const bool frameHasHeader = static_cast(*p) == 0; - if (frameHasHeader) { - constexpr uint32_t FrameHeaderSize = 5 * 2; - p += FrameHeaderSize; - } - while (p != end) { - const auto val = static_cast(*p++); - if (IsCelTransparent(val)) { - continue; - } - for (unsigned i = 0; i < val; ++i) { - const auto color = static_cast(*p); - *p++ = static_cast(translation[color]); - } - } - } -} - -} // namespace devilution diff --git a/Source/engine/render/cel_render.hpp b/Source/engine/render/cel_render.hpp deleted file mode 100644 index a90934021..000000000 --- a/Source/engine/render/cel_render.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file cel_render.hpp - * - * CEL rendering. - */ -#pragma once - -#include - -#include "engine.h" -#include "engine/cel_sprite.hpp" -#include "engine/point.hpp" -#include "items.h" - -namespace devilution { - -/** - * Returns a pair of X coordinates containing the start (inclusive) and end (exclusive) - * of fully transparent columns in the sprite. - */ -std::pair MeasureSolidHorizontalBounds(CelSprite cel, int frame = 0); - -/** - * @brief Apply the color swaps to a CEL sprite - * - * @param p CEL buffer - * @param translation Palette translation table - */ -void CelApplyTrans(byte *p, const std::array &translation); - -/** - * @brief Blit CEL sprite to the back buffer at the given coordinates - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelDrawTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Blit CEL sprite to the given buffer, does not perform bounds-checking. - * @param out Target buffer - * @param position Coordinate in the target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelDrawUnsafeTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Same as CelDrawTo but with the option to skip parts of the top and bottom of the sprite - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelClippedDrawTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - * @param tbl Palette translation table - */ -void CelDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame, uint8_t *tbl); - -/** - * @brief Same as CelDrawLightTo but with the option to skip parts of the top and bottom of the sprite - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelClippedDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Same as CelBlitLightSafeTo but with transparency applied - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelClippedBlitLightTransTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates, translated to a red hue - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelDrawLightRedTo(const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Blit item's CEL sprite recolored red if not usable, normal if usable - * @param item Item being drawn - * @param out Target buffer - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - */ -void CelDrawItem(const Item &item, const Surface &out, Point position, CelSprite cel, int frame); - -/** - * @brief Blit a solid colder shape one pixel larger than the given sprite shape, to the target buffer at the given coordianates - * @param out Target buffer - * @param col Color index from current palette - * @param position Target buffer coordinate - * @param cel CEL sprite - * @param frame CEL frame number - * @param skipColorIndexZero If true, color in index 0 will be treated as transparent (these are typically used for shadows in sprites) - */ -void Cl2DrawOutline(const Surface &out, uint8_t col, Point position, CelSprite cel, int frame, bool skipColorIndexZero = true); - -} // namespace devilution diff --git a/Source/engine/render/cl2_render.cpp b/Source/engine/render/cl2_render.cpp index e2d0b8715..63ce32016 100644 --- a/Source/engine/render/cl2_render.cpp +++ b/Source/engine/render/cl2_render.cpp @@ -71,7 +71,7 @@ BlitCommand Cl2GetBlitCommand(const uint8_t *src) */ void Cl2Blit(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth) { - DoRenderBackwards( + DoRenderBackwards( out, position, reinterpret_cast(pRLEBytes), nDataSize, nWidth, BlitDirect {}); } @@ -87,13 +87,13 @@ void Cl2Blit(const Surface &out, Point position, const byte *pRLEBytes, int nDat */ void Cl2BlitTRN(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t *pTable) { - DoRenderBackwards( + DoRenderBackwards( out, position, reinterpret_cast(pRLEBytes), nDataSize, nWidth, BlitWithMap { pTable }); } void Cl2BlitBlendedTRN(const Surface &out, Point position, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t *pTable) { - DoRenderBackwards( + DoRenderBackwards( out, position, reinterpret_cast(pRLEBytes), nDataSize, nWidth, BlitBlendedWithMap { pTable }); } diff --git a/Source/engine/render/common_impl.h b/Source/engine/render/common_impl.h index 69593a20b..7ff0ca1ed 100644 --- a/Source/engine/render/common_impl.h +++ b/Source/engine/render/common_impl.h @@ -90,16 +90,6 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT const uint8_t *SkipRestOfLineWithOverrun( return src; } -template -DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void SkipLinesForRenderBackwards( - Point &position, RenderSrcBackwards &src, int_fast16_t dstHeight) -{ - while (position.y >= dstHeight && src.begin != src.end) { - src.begin = SkipRestOfLine(src.begin, src.width); - --position.y; - } -} - // Returns the horizontal overrun. template DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT int_fast16_t SkipLinesForRenderBackwardsWithOverrun( @@ -124,20 +114,12 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void SkipLinesForRenderForwards(Point &posit } } -template < - bool TransparentCommandCanCrossLines, - GetBlitCommandFn GetBlitCommand, - typename BlitFn> +template void DoRenderBackwardsClipY( const Surface &out, Point position, RenderSrcBackwards src, BlitFn &&blitFn) { // Skip the bottom clipped lines. - int_fast16_t xOffset; - if (TransparentCommandCanCrossLines) { - xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h()); - } else { - SkipLinesForRenderBackwards(position, src, out.h()); - } + int_fast16_t xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h()); if (src.begin >= src.end) return; @@ -145,11 +127,8 @@ void DoRenderBackwardsClipY( const auto *dstBegin = out.begin(); const int dstPitch = out.pitch(); while (src.begin != src.end && dst >= dstBegin) { - auto remainingWidth = static_cast(src.width); - if (TransparentCommandCanCrossLines) { - remainingWidth -= xOffset; - dst += xOffset; - } + auto remainingWidth = static_cast(src.width) - xOffset; + dst += xOffset; while (remainingWidth > 0) { BlitCommand cmd = GetBlitCommand(src.begin); blitFn(cmd, dst, src.begin + 1); @@ -159,32 +138,22 @@ void DoRenderBackwardsClipY( } dst -= dstPitch + src.width - remainingWidth; - if (TransparentCommandCanCrossLines) { - if (remainingWidth < 0) { - const auto skipSize = GetSkipSize(-remainingWidth, static_cast(src.width)); - xOffset = skipSize.xOffset; - dst -= skipSize.wholeLines * dstPitch; - } else { - xOffset = 0; - } + if (remainingWidth < 0) { + const auto skipSize = GetSkipSize(-remainingWidth, static_cast(src.width)); + xOffset = skipSize.xOffset; + dst -= skipSize.wholeLines * dstPitch; + } else { + xOffset = 0; } } } -template < - bool TransparentCommandCanCrossLines, - GetBlitCommandFn GetBlitCommand, - typename BlitFn> +template void DoRenderBackwardsClipXY( const Surface &out, Point position, RenderSrcBackwards src, ClipX clipX, BlitFn &&blitFn) { // Skip the bottom clipped lines. - int_fast16_t xOffset; - if (TransparentCommandCanCrossLines) { - xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h()); - } else { - SkipLinesForRenderBackwards(position, src, out.h()); - } + int_fast16_t xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h()); if (src.begin >= src.end) return; @@ -197,13 +166,10 @@ void DoRenderBackwardsClipXY( // Skip initial src if clipping on the left. // Handles overshoot, i.e. when the RLE segment goes into the unclipped area. int_fast16_t remainingWidth = clipX.width; - int_fast16_t remainingLeftClip = clipX.left; - if (TransparentCommandCanCrossLines) { - remainingLeftClip -= xOffset; - if (remainingLeftClip < 0) { - dst += std::min(remainingWidth, -remainingLeftClip); - remainingWidth += remainingLeftClip; - } + int_fast16_t remainingLeftClip = clipX.left - xOffset; + if (remainingLeftClip < 0) { + dst += std::min(remainingWidth, -remainingLeftClip); + remainingWidth += remainingLeftClip; } while (remainingLeftClip > 0) { BlitCommand cmd = GetBlitCommand(src.begin); @@ -234,31 +200,24 @@ void DoRenderBackwardsClipXY( // Set dst to (position.y - 1, position.x) dst -= dstPitch + clipX.width; - if (TransparentCommandCanCrossLines) { - // `remainingWidth` can be negative, in which case it is the amount of pixels - // that the source has overran the line. - remainingWidth += clipX.right; - SkipSize skipSize { 0, 0 }; - if (remainingWidth > 0) { - skipSize.xOffset = static_cast(src.width) - remainingWidth; - src.begin = SkipRestOfLineWithOverrun( - src.begin, static_cast(src.width), skipSize); - --skipSize.wholeLines; - } else if (remainingWidth < 0) { - skipSize = GetSkipSize(-remainingWidth, static_cast(src.width)); - } - xOffset = skipSize.xOffset; - dst -= dstPitch * skipSize.wholeLines; - } else { - src.begin = SkipRestOfLine(src.begin, clipX.right + remainingWidth); + // `remainingWidth` can be negative, in which case it is the amount of pixels + // that the source has overran the line. + remainingWidth += clipX.right; + SkipSize skipSize { 0, 0 }; + if (remainingWidth > 0) { + skipSize.xOffset = static_cast(src.width) - remainingWidth; + src.begin = SkipRestOfLineWithOverrun( + src.begin, static_cast(src.width), skipSize); + --skipSize.wholeLines; + } else if (remainingWidth < 0) { + skipSize = GetSkipSize(-remainingWidth, static_cast(src.width)); } + xOffset = skipSize.xOffset; + dst -= dstPitch * skipSize.wholeLines; } } -template < - bool TransparentCommandCanCrossLines, - GetBlitCommandFn GetBlitCommand, - typename BlitFn> +template void DoRenderBackwards( const Surface &out, Point position, const uint8_t *src, size_t srcSize, unsigned srcWidth, BlitFn &&blitFn) @@ -268,10 +227,10 @@ void DoRenderBackwards( return; RenderSrcBackwards srcForBackwards { src, src + srcSize, static_cast(srcWidth) }; if (static_cast(clipX.width) == srcWidth) { - DoRenderBackwardsClipY( + DoRenderBackwardsClipY( out, position, srcForBackwards, std::forward(blitFn)); } else { - DoRenderBackwardsClipXY( + DoRenderBackwardsClipXY( out, position, srcForBackwards, clipX, std::forward(blitFn)); } }