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);