mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-31 19:47:06 +01:00
Use one UI drop shadow for text and atlas images, fix Windows build
Text and the SVG button images are mixed on screen, so they now share UIDropShadowParams (3 UI units of blur, 0.66 intensity, no offset, the atlas's existing look) instead of the text having its own. draw_text.cpp included <windows.h> directly, whose min/max macros broke the std::max calls added here. Include CommonWindows.h instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fcfac13643
commit
dea182f1d8
7 files changed
+24
-24
No files matched your search
@@ -23,7 +23,6 @@
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/Render/AtlasGen.h"
|
||||
#include "Common/Render/DropShadow.h"
|
||||
|
||||
typedef unsigned short u16;
|
||||
|
||||
@@ -241,10 +240,7 @@ void Add1PxTransparentBorder(Image &img) {
|
||||
img.h += 2;
|
||||
}
|
||||
|
||||
void AddDropShadow(Image &img, int shadowSize, float intensity) {
|
||||
DropShadowParams params;
|
||||
params.radius = std::max(1, (int)(shadowSize * img.scale));
|
||||
params.intensity = intensity;
|
||||
void AddDropShadow(Image &img, const DropShadowParams ¶ms) {
|
||||
const int pad = params.Padding();
|
||||
std::vector<u32> newData((img.w + pad * 2) * (img.h + pad * 2));
|
||||
CompositeDropShadow(img.dat.data(), img.w, img.h, newData.data(), img.w + pad * 2, params);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Common/Render/DropShadow.h"
|
||||
#include "Common/Render/TextureAtlas.h"
|
||||
|
||||
struct ImageU8 {
|
||||
@@ -92,7 +93,7 @@ struct Image {
|
||||
};
|
||||
|
||||
// Slow.
|
||||
void AddDropShadow(Image &img, int shadowSize, float intensity);
|
||||
void AddDropShadow(Image &img, const DropShadowParams ¶ms);
|
||||
|
||||
// To improve filtering.
|
||||
void Add1PxTransparentBorder(Image &img);
|
||||
|
||||
@@ -20,6 +20,17 @@
|
||||
|
||||
#include "Common/Render/DropShadow.h"
|
||||
|
||||
// In UI units.
|
||||
static constexpr float UI_SHADOW_RADIUS = 3.0f;
|
||||
static constexpr float UI_SHADOW_INTENSITY = 0.66f;
|
||||
|
||||
DropShadowParams UIDropShadowParams(float pixelsPerUnit) {
|
||||
DropShadowParams params;
|
||||
params.radius = std::max(1, (int)(UI_SHADOW_RADIUS * pixelsPerUnit));
|
||||
params.intensity = UI_SHADOW_INTENSITY;
|
||||
return params;
|
||||
}
|
||||
|
||||
void CompositeDropShadow(const u32 *src, int w, int h, u32 *dst, int dstStride, const DropShadowParams ¶ms) {
|
||||
const int radius = std::max(1, params.radius);
|
||||
const int pad = params.Padding();
|
||||
|
||||
@@ -38,6 +38,9 @@ struct DropShadowParams {
|
||||
}
|
||||
};
|
||||
|
||||
// The UI's shadow, used for both the atlas images and text, so the two match on screen.
|
||||
DropShadowParams UIDropShadowParams(float pixelsPerUnit);
|
||||
|
||||
// src is premultiplied RGBA with alpha in the top byte. Writes it composited over its shadow to dst,
|
||||
// (w + 2 * padding) x (h + 2 * padding) pixels with the image centered. Since the shadow is black,
|
||||
// only alpha changes under the image.
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
#if defined(__linux__) || defined(__FreeBSD__) && !defined(__ANDROID__)
|
||||
# include <dlfcn.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# include "Common/CommonWindows.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "ext/xxhash.h"
|
||||
@@ -46,13 +45,6 @@ static bool IsRenderDocLoaded() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Drop shadow blur radius and offset as fractions of the font size, which is in UI units. The bitmap
|
||||
// has 1/dpiScale_ pixels per UI unit, so at higher DPI the blur spans more pixels.
|
||||
static constexpr float SHADOW_BLUR = 1.0f / 7.0f;
|
||||
static constexpr float SHADOW_OFFSET = 1.0f / 16.0f;
|
||||
// Blurring thin strokes spreads them thin, so boost the shadow's alpha a bit (clamped).
|
||||
static constexpr float SHADOW_STRENGTH = 1.5f;
|
||||
|
||||
size_t TextCacheKeyHash::operator()(const TextCacheKey &key) const {
|
||||
uint32_t maxWidthBits, scaleBits;
|
||||
memcpy(&maxWidthBits, &key.maxWidth, sizeof(maxWidthBits));
|
||||
@@ -274,11 +266,8 @@ bool TextDrawer::DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStri
|
||||
}
|
||||
|
||||
void TextDrawer::AddDropShadow(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat srcFormat) const {
|
||||
const float pixelsPerUnit = 1.0f / dpiScale_;
|
||||
DropShadowParams params;
|
||||
params.radius = std::max(1, (int)roundf(fontStyle_.sizePts * SHADOW_BLUR * pixelsPerUnit));
|
||||
params.offsetX = params.offsetY = std::max(1, (int)roundf(fontStyle_.sizePts * SHADOW_OFFSET * pixelsPerUnit));
|
||||
params.intensity = SHADOW_STRENGTH;
|
||||
// The bitmap has 1/dpiScale_ pixels per UI unit, so at higher DPI the blur spans more pixels.
|
||||
const DropShadowParams params = UIDropShadowParams(1.0f / dpiScale_);
|
||||
const int pad = params.Padding();
|
||||
|
||||
const int srcW = entry.bmWidth;
|
||||
|
||||
+1
-1
@@ -401,7 +401,7 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int
|
||||
if (!images[i].IsEmpty()) {
|
||||
if (imageIDs[i].addShadow) {
|
||||
// DEBUG_LOG(Log::G3D, "Adding drop shadow to %.*s", STR_VIEW(imageIDs[i].id));
|
||||
AddDropShadow(images[i], 3, 0.66f);
|
||||
AddDropShadow(images[i], UIDropShadowParams(images[i].scale));
|
||||
} else {
|
||||
// Make sure there are transparent pixels to filter from.
|
||||
Add1PxTransparentBorder(images[i]);
|
||||
|
||||
@@ -3697,7 +3697,7 @@ bool TestTextDrawerCache() {
|
||||
EXPECT_EQ_INT((int)bitmap.size(), entry1.bmWidth * entry1.bmHeight * 4);
|
||||
const uint32_t *pixels = (const uint32_t *)bitmap.data();
|
||||
auto pixel = [&](int x, int y) { return pixels[(y + pad) * entry1.bmWidth + x + pad]; };
|
||||
// The text stays opaque white, the shadow is black and partly transparent below-right of it, and the far corner is empty.
|
||||
// The text stays opaque white, the shadow around it is black and partly transparent, and the far corner is empty.
|
||||
EXPECT_EQ_INT(pixel(8, 8), 0xFFFFFFFF);
|
||||
EXPECT_EQ_INT(pixel(12, 12) & 0x00FFFFFF, 0);
|
||||
EXPECT_TRUE((pixel(12, 12) >> 24) > 0);
|
||||
@@ -3708,7 +3708,7 @@ bool TestTextDrawerCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The atlas shadow has no offset, so it pads the image evenly and stays symmetric around it.
|
||||
// The UI shadow has no offset, so it pads the image evenly and stays symmetric around it.
|
||||
bool TestAtlasDropShadow() {
|
||||
Image img;
|
||||
img.scale = 2.0f;
|
||||
@@ -3718,7 +3718,7 @@ bool TestAtlasDropShadow() {
|
||||
img.set1(x, y, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
AddDropShadow(img, 3, 0.66f);
|
||||
AddDropShadow(img, UIDropShadowParams(img.scale));
|
||||
EXPECT_EQ_INT(img.w, 8 + 12);
|
||||
EXPECT_EQ_INT(img.h, 8 + 12);
|
||||
EXPECT_EQ_HEX(img.get1(6 + 3, 6 + 3), 0xFFFFFFFF);
|
||||
|
||||
Reference in new issue
Block a user