From 12de70550ba7516263d6b91ea2ff575041c684bf Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 11 Apr 2022 23:56:23 +0100 Subject: [PATCH] Fix an OOB in CEL/CL2 outline rendering This OOB happened when rendering a sprite so that it is exactly off-screen (touching the border but not visible) on top/bottom while also being only partly off-screen on the left or right. --- Source/engine/render/cel_render.cpp | 29 ++++++++++++++++++++++------- Source/engine/render/cl2_render.cpp | 27 +++++++++++++++++++++------ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/Source/engine/render/cel_render.cpp b/Source/engine/render/cel_render.cpp index 3bd2584ba..4b9244ac7 100644 --- a/Source/engine/render/cel_render.cpp +++ b/Source/engine/render/cel_render.cpp @@ -436,9 +436,17 @@ void RenderCelOutlineClippedXY(const Surface &out, Point position, const byte *s if (position.y == dstHeight) { // After-bottom line - can only draw north. - src = RenderCelOutlineRowClipped( - out, position, src, clipX, color); + if (position.x <= 0) { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } else if (position.x + clipX.width >= out.w()) { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } else { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } + --position.y; } if (src == srcEnd) @@ -507,10 +515,17 @@ void RenderCelOutlineClippedXY(const Surface &out, Point position, const byte *s 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, clipX, color); + // After-bottom line - can only draw south. + if (position.x <= 0) { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } else if (position.x + clipX.width >= out.w()) { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } else { + src = RenderCelOutlineRowClipped(out, position, src, clipX, color); + } } } diff --git a/Source/engine/render/cl2_render.cpp b/Source/engine/render/cl2_render.cpp index 9bc49f5d1..1a4dea5aa 100644 --- a/Source/engine/render/cl2_render.cpp +++ b/Source/engine/render/cl2_render.cpp @@ -641,8 +641,16 @@ void RenderCl2OutlineClippedXY(const Surface &out, Point position, const byte *s if (position.y == dstHeight) { // After-bottom line - can only draw north. - src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + if (position.x <= 0) { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } else if (position.x + clipX.width >= out.w()) { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } else { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } position.y -= static_cast(skipSize.wholeLines); } if (src == srcEnd) @@ -711,10 +719,17 @@ void RenderCl2OutlineClippedXY(const Surface &out, Point position, const byte *s return; if (position.y == -1) { - // Special case: the top of the sprite is 1px below the last line, render just the outline above. - RenderCl2OutlineRowClipped( - out, position, src, srcWidth, clipX, color, skipSize); + // Before-top line - can only draw south. + if (position.x <= 0) { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } else if (position.x + clipX.width >= out.w()) { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } else { + src = RenderCl2OutlineRowClipped(out, position, src, srcWidth, clipX, color, skipSize); + } } }