Browse Source

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.
pull/4412/head
Gleb Mazovetskiy 4 years ago committed by Anders Jenbo
parent
commit
12de70550b
  1. 29
      Source/engine/render/cel_render.cpp
  2. 27
      Source/engine/render/cl2_render.cpp

29
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<SkipColorIndexZero, /*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true>(
out, position, src, clipX, color);
if (position.x <= 0) {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/true, /*CheckLastColumn=*/false>(out, position, src, clipX, color);
} else if (position.x + clipX.width >= out.w()) {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/false, /*CheckLastColumn=*/true>(out, position, src, clipX, color);
} else {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true>(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<SkipColorIndexZero, /*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true>(
out, position, src, clipX, color);
// After-bottom line - can only draw south.
if (position.x <= 0) {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/true, /*CheckLastColumn=*/false>(out, position, src, clipX, color);
} else if (position.x + clipX.width >= out.w()) {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/false, /*CheckLastColumn=*/true>(out, position, src, clipX, color);
} else {
src = RenderCelOutlineRowClipped<SkipColorIndexZero, /*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true>(out, position, src, clipX, color);
}
}
}

27
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</*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true>(out, position, src, srcWidth, clipX, color, skipSize);
if (position.x <= 0) {
src = RenderCl2OutlineRowClipped</*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/true, /*CheckLastColumn=*/false>(out, position, src, srcWidth, clipX, color, skipSize);
} else if (position.x + clipX.width >= out.w()) {
src = RenderCl2OutlineRowClipped</*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/false, /*CheckLastColumn=*/true>(out, position, src, srcWidth, clipX, color, skipSize);
} else {
src = RenderCl2OutlineRowClipped</*North=*/true, /*West=*/false, /*South=*/false, /*East=*/false,
/*ClipWidth=*/true>(out, position, src, srcWidth, clipX, color, skipSize);
}
position.y -= static_cast<int>(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</*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true>(
out, position, src, srcWidth, clipX, color, skipSize);
// Before-top line - can only draw south.
if (position.x <= 0) {
src = RenderCl2OutlineRowClipped</*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/true, /*CheckLastColumn=*/false>(out, position, src, srcWidth, clipX, color, skipSize);
} else if (position.x + clipX.width >= out.w()) {
src = RenderCl2OutlineRowClipped</*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true, /*CheckFirstColumn=*/false, /*CheckLastColumn=*/true>(out, position, src, srcWidth, clipX, color, skipSize);
} else {
src = RenderCl2OutlineRowClipped</*North=*/false, /*West=*/false, /*South=*/true, /*East=*/false,
/*ClipWidth=*/true>(out, position, src, srcWidth, clipX, color, skipSize);
}
}
}

Loading…
Cancel
Save