From 0bb70de3f0d5c8eb613f6659b18cffc2e5ee7fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 19 Sep 2025 11:23:48 -0600 Subject: [PATCH] Correct the drop shadow --- Common/Render/AtlasGen.cpp | 60 +++++++++++++++++--------------------- Common/Render/AtlasGen.h | 2 +- UI/UIAtlas.cpp | 2 +- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/Common/Render/AtlasGen.cpp b/Common/Render/AtlasGen.cpp index 2d0998e2df..04fd83e3ba 100644 --- a/Common/Render/AtlasGen.cpp +++ b/Common/Render/AtlasGen.cpp @@ -252,53 +252,47 @@ inline u32 blendOver(u32 dst, u32 src) { ((u32)(outB * 255 + 0.5f) << 0); } -void addDropShadow(Image &img, int shadowSize, int offsetX, int offsetY) { +void addDropShadow(Image &img, int shadowSize) { int radius = std::max(1, (int)(shadowSize * img.scale)); - // Compute required expansion on each side - int left = radius + std::max(0, -offsetX); - int right = radius + std::max(0, offsetX); - int top = radius + std::max(0, -offsetY); - int bottom = radius + std::max(0, offsetY); + // Expand canvas so blur has space on all sides + int newW = img.w + radius * 2; + int newH = img.h + radius * 2; - int newW = img.w + left + right; - int newH = img.h + top + bottom; - - std::vector newData(newW * newH, 0); - - // Extract alpha - std::vector alpha(img.w * img.h, 0.0f); - for (int i = 0; i < img.w * img.h; i++) { - u32 c = img.dat[i]; - alpha[i] = ((c >> 24) & 0xFF) / 255.0f; - } - - // Blur - std::vector blurred(img.w * img.h, 0.0f); - blurAlpha(alpha, blurred, img.w, img.h, radius); - - // Draw shadow (black, blurred alpha) + // Expanded alpha buffer + std::vector alpha(newW * newH, 0.0f); for (int y = 0; y < img.h; y++) { for (int x = 0; x < img.w; x++) { - float a = blurred[y * img.w + x]; + float a = ((img.dat[y * img.w + x] >> 24) & 0xFF) / 255.0f; + alpha[(y + radius) * newW + (x + radius)] = a; + } + } + + // Blur the expanded alpha + std::vector blurred(newW * newH, 0.0f); + blurAlpha(alpha, blurred, newW, newH, radius); + + // Target buffer with transparent background + std::vector newData(newW * newH, 0); + + // Draw shadow (black, blurred alpha) + for (int y = 0; y < newH; y++) { + for (int x = 0; x < newW; x++) { + float a = blurred[y * newW + x]; if (a > 0.001f) { - int nx = x + left + offsetX; - int ny = y + top + offsetY; - if (nx >= 0 && ny >= 0 && nx < newW && ny < newH) { - u32 shadowColor = ((u32)(a * 180) << 24); // semi-transparent black - newData[ny * newW + nx] = shadowColor; - } + u32 shadowColor = ((u32)(a * 180) << 24); // semi-transparent black + newData[y * newW + x] = blendOver(newData[y * newW + x], shadowColor); } } } - // Composite original image on top + // Composite original image on top (centered in expanded buffer) for (int y = 0; y < img.h; y++) { for (int x = 0; x < img.w; x++) { u32 c = img.dat[y * img.w + x]; if ((c >> 24) & 0xFF) { - int nx = x + left; - int ny = y + top; + int nx = x + radius; + int ny = y + radius; newData[ny * newW + nx] = blendOver(newData[ny * newW + nx], c); } } diff --git a/Common/Render/AtlasGen.h b/Common/Render/AtlasGen.h index 951276f53f..8e79cdb3b1 100644 --- a/Common/Render/AtlasGen.h +++ b/Common/Render/AtlasGen.h @@ -71,7 +71,7 @@ struct Image { std::vector dat; }; -void addDropShadow(Image &img, int shadowSize, int offsetX, int offsetY); +void addDropShadow(Image &img, int shadowSize); struct Data { // item ID diff --git a/UI/UIAtlas.cpp b/UI/UIAtlas.cpp index 157e0491d7..c813ce8878 100644 --- a/UI/UIAtlas.cpp +++ b/UI/UIAtlas.cpp @@ -239,7 +239,7 @@ Draw::Texture *GenerateUIAtlas(Draw::DrawContext *draw, Atlas *atlas) { } img.scale = scale; - addDropShadow(img, 4, 0, 0); + addDropShadow(img, 4); // pngSave(Path(std::string("../buttons_") + PNGNameFromID(shapeId)), img.data(), img.width(), img.height(), 4); }