From cd6c20f783397462021fbfa41d729cae96bd4529 Mon Sep 17 00:00:00 2001 From: DotDebian Date: Sun, 4 Oct 2026 17:59:31 +0200 Subject: [PATCH] feat(font): implement sceFontGetResolutionDpi Report the horizontal and vertical resolution kept in the font handle's style block, as set when the font is opened (72 dpi) or by sceFontSetResolutionDpi. Error handling follows the other handle getters: an invalid handle or two null outputs fail and clear the outputs. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libSceFont/src/Style.cpp | 16 +++++ .../libs/prx/libSceFont/src/Unimplemented.cpp | 5 -- core/libs/tests/GuestFont.cpp | 62 +++++++++++++++++++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/core/libs/prx/libSceFont/src/Style.cpp b/core/libs/prx/libSceFont/src/Style.cpp index 42c4d9194..e5503b886 100644 --- a/core/libs/prx/libSceFont/src/Style.cpp +++ b/core/libs/prx/libSceFont/src/Style.cpp @@ -56,6 +56,11 @@ void ResetScaleOutputs(float* w, float* h) { if (h) *h = 0.0f; } +void ResetDpiOutputs(std::uint32_t* hDpi, std::uint32_t* vDpi) { + if (hDpi) *hDpi = 0; + if (vDpi) *vDpi = 0; +} + void ResetWeightOutputs(float* weightXScale, float* weightYScale, std::uint32_t* mode) { if (weightXScale) *weightXScale = 1.0f; if (weightYScale) *weightYScale = 1.0f; @@ -117,6 +122,17 @@ int APS5_VABI sceFontGetScalePoint(FontHandle fontHandle, float* w, float* h) { return rc; } +int APS5_VABI sceFontGetResolutionDpi(FontHandle fontHandle, std::uint32_t* hDpi, std::uint32_t* vDpi) { + const int rc = ReadFontStyle(fontHandle, true, [&](FontHandleNative* font) { + if (!hDpi && !vDpi) return SCE_FONT_ERROR_INVALID_PARAMETER; + if (hDpi) *hDpi = font->style.dpi_x; + if (vDpi) *vDpi = font->style.dpi_y; + return SCE_FONT_OK; + }); + if (rc != SCE_FONT_OK) ResetDpiOutputs(hDpi, vDpi); + return rc; +} + int APS5_VABI sceFontGetEffectSlant(FontHandle fontHandle, float* slantRatio) { const int rc = ReadFontStyle(fontHandle, true, [&](FontHandleNative* font) { return StyleStateGetSlantRatio(&font->style, slantRatio); }); if (rc != SCE_FONT_OK && slantRatio) *slantRatio = 0.0f; diff --git a/core/libs/prx/libSceFont/src/Unimplemented.cpp b/core/libs/prx/libSceFont/src/Unimplemented.cpp index de6b6e3d0..16ac20268 100644 --- a/core/libs/prx/libSceFont/src/Unimplemented.cpp +++ b/core/libs/prx/libSceFont/src/Unimplemented.cpp @@ -127,11 +127,6 @@ int APS5_VABI sceFontGetRenderScaledKerning() { return 0; } -int APS5_VABI sceFontGetResolutionDpi() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceFontGetScriptLanguage() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/tests/GuestFont.cpp b/core/libs/tests/GuestFont.cpp index 36d1fbf9c..569b3aef4 100644 --- a/core/libs/tests/GuestFont.cpp +++ b/core/libs/tests/GuestFont.cpp @@ -1,7 +1,11 @@ #include "prx/libSceFont/include/FontTypes.hpp" +#include #include #include #include +#include +#include +#include extern "C" { int APS5_VABI sceFontMemoryInit(FontMemory*, void*, std::uint32_t, const FontMemoryInterface*, void*, FontMemoryDestroyFunction, void*); @@ -14,6 +18,9 @@ int APS5_VABI sceFontSupportSystemFonts(FontLibrary); int APS5_VABI sceFontSupportExternalFonts(FontLibrary, std::uint32_t, std::uint32_t); int APS5_VABI sceFontOpenFontSet(FontLibrary, std::uint32_t, std::uint32_t, const FontOpenDetail*, FontHandle*); int APS5_VABI sceFontOpenFontMemory(FontLibrary, const void*, std::uint32_t, const FontOpenDetail*, FontHandle*); +int APS5_VABI sceFontCloseFont(FontHandle); +int APS5_VABI sceFontSetResolutionDpi(FontHandle, std::uint32_t, std::uint32_t); +int APS5_VABI sceFontGetResolutionDpi(FontHandle, std::uint32_t*, std::uint32_t*); const void* APS5_VABI sceFontSelectLibraryFt(int); const void* APS5_VABI sceFontSelectRendererFt(int); } @@ -36,6 +43,40 @@ static void APS5_VABI Release(void*, void* pointer) { std::free(pointer); } +static void Put16(std::vector& out, int value) { + out.push_back(static_cast((value >> 8) & 0xFF)); + out.push_back(static_cast(value & 0xFF)); +} + +static std::vector Words(std::initializer_list values) { + std::vector out; + for (const int value : values) Put16(out, value); + return out; +} + +static std::vector EmptyGlyphFont() { + const std::vector>> tables = { + {"glyf", Words({0, 0})}, + {"head", Words({1, 0, 1, 0, 0, 0, 0x5F0F, 0x3CF5, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0})}, + {"hhea", Words({1, 0, 800, -200, 0, 500, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1})}, + {"hmtx", Words({500, 0})}, + {"loca", Words({0, 0})}, + {"maxp", Words({1, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0})}, + }; + std::vector font = Words({1, 0, static_cast(tables.size()), 64, 2, 32}); + int offset = 12 + 16 * static_cast(tables.size()); + for (const auto& table : tables) { + font.insert(font.end(), table.first, table.first + 4); + for (const int value : {0, 0, offset >> 16, offset & 0xFFFF, 0, static_cast(table.second.size())}) Put16(font, value); + offset += static_cast((table.second.size() + 3) & ~std::size_t{3}); + } + for (const auto& table : tables) { + font.insert(font.end(), table.second.begin(), table.second.end()); + font.resize((font.size() + 3) & ~std::size_t{3}); + } + return font; +} + int main() { constexpr std::uint32_t SystemFontSet = 0x18070043u; const FontMemoryInterface iface{Allocate, Release, nullptr, nullptr, nullptr, nullptr}; @@ -62,6 +103,27 @@ int main() { Require(sceFontOpenFontMemory(library, nullptr, 0, nullptr, &font) == SCE_FONT_ERROR_INVALID_PARAMETER && font == nullptr); Require(sceFontOpenFontMemory(library, notAFont, sizeof(notAFont), nullptr, &font) == SCE_FONT_ERROR_NO_SUPPORT_FORMAT && font == nullptr); + const std::vector fontData = EmptyGlyphFont(); + Require(sceFontOpenFontMemory(library, fontData.data(), static_cast(fontData.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr); + std::uint32_t hDpi = 1; + std::uint32_t vDpi = 1; + Require(sceFontGetResolutionDpi(font, &hDpi, &vDpi) == SCE_FONT_OK && hDpi == 72 && vDpi == 72); + Require(sceFontSetResolutionDpi(font, 96, 144) == SCE_FONT_OK); + Require(sceFontGetResolutionDpi(font, &hDpi, &vDpi) == SCE_FONT_OK && hDpi == 96 && vDpi == 144); + hDpi = 1; + vDpi = 1; + Require(sceFontGetResolutionDpi(font, &hDpi, nullptr) == SCE_FONT_OK && hDpi == 96); + Require(sceFontGetResolutionDpi(font, nullptr, &vDpi) == SCE_FONT_OK && vDpi == 144); + Require(sceFontGetResolutionDpi(font, nullptr, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + Require(sceFontSetResolutionDpi(font, 0, 300) == SCE_FONT_OK); + Require(sceFontGetResolutionDpi(font, &hDpi, &vDpi) == SCE_FONT_OK && hDpi == 72 && vDpi == 300); + Require(sceFontGetResolutionDpi(nullptr, &hDpi, &vDpi) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && hDpi == 0 && vDpi == 0); + FontHandleOpaque unopened{}; + hDpi = 1; + vDpi = 1; + Require(sceFontGetResolutionDpi(&unopened, &hDpi, &vDpi) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && hDpi == 0 && vDpi == 0); + Require(sceFontCloseFont(font) == SCE_FONT_OK); + FontRenderer renderer = nullptr; Require(sceFontCreateRenderer(&memory, sceFontSelectRendererFt(0), &renderer) == SCE_FONT_OK && renderer != nullptr); Require(sceFontDestroyRenderer(&renderer) == SCE_FONT_OK && renderer == nullptr);