diff --git a/core/libs/prx/libSceFont/include/FontInternal.hpp b/core/libs/prx/libSceFont/include/FontInternal.hpp index b65648a0d..b2a742c29 100644 --- a/core/libs/prx/libSceFont/include/FontInternal.hpp +++ b/core/libs/prx/libSceFont/include/FontInternal.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ struct FontState { FT_Face face = nullptr; float scaleW = 16.0f; float scaleH = 16.0f; + std::map scriptLanguages; + std::map typographicFeatures; FontState() = default; FontState(const FontState&) = delete; diff --git a/core/libs/prx/libSceFont/src/Style.cpp b/core/libs/prx/libSceFont/src/Style.cpp index e5503b886..67e7abe13 100644 --- a/core/libs/prx/libSceFont/src/Style.cpp +++ b/core/libs/prx/libSceFont/src/Style.cpp @@ -51,6 +51,30 @@ int ReadFontStyle(FontHandle fontHandle, bool checkMagic, Getter&& getter) { return rc; } +template +int AccessFontSettings(FontHandle fontHandle, Access&& access) { + return ReadFontStyle(fontHandle, true, [&](FontHandleNative*) { + FontState* state = TryGetState(fontHandle); + return state ? access(*state) : SCE_FONT_ERROR_INVALID_FONT_HANDLE; + }); +} + +int SetFontSetting(FontHandle fontHandle, std::map FontState::*table, int key, int value) { + return AccessFontSettings(fontHandle, [&](FontState& state) { + (state.*table)[key] = value; + return SCE_FONT_OK; + }); +} + +int GetFontSetting(FontHandle fontHandle, std::map FontState::*table, int key, int* value) { + if (!value) return SCE_FONT_ERROR_INVALID_PARAMETER; + return AccessFontSettings(fontHandle, [&](FontState& state) { + const auto found = (state.*table).find(key); + *value = found == (state.*table).end() ? 0 : found->second; + return SCE_FONT_OK; + }); +} + void ResetScaleOutputs(float* w, float* h) { if (w) *w = 0.0f; if (h) *h = 0.0f; @@ -77,6 +101,22 @@ float ClampWeightDelta(float scale) { extern "C" { +int APS5_VABI sceFontSetScriptLanguage(FontHandle fontHandle, int fontScript, int fontLanguage) { + return SetFontSetting(fontHandle, &FontState::scriptLanguages, fontScript, fontLanguage); +} + +int APS5_VABI sceFontGetScriptLanguage(FontHandle fontHandle, int fontScript, int* fontLanguage) { + return GetFontSetting(fontHandle, &FontState::scriptLanguages, fontScript, fontLanguage); +} + +int APS5_VABI sceFontSetTypographicDesign(FontHandle fontHandle, int typographic, int feature) { + return SetFontSetting(fontHandle, &FontState::typographicFeatures, typographic, feature); +} + +int APS5_VABI sceFontGetTypographicDesign(FontHandle fontHandle, int typographic, int* feature) { + return GetFontSetting(fontHandle, &FontState::typographicFeatures, typographic, feature); +} + int APS5_VABI sceFontSetScalePixel(FontHandle fontHandle, float w, float h) { return UpdateFontStyle(fontHandle, [&](FontHandleNative* font) { const int changed = StyleStateSetScalePixel(&font->style, w, h); diff --git a/core/libs/prx/libSceFont/src/Unimplemented.cpp b/core/libs/prx/libSceFont/src/Unimplemented.cpp index 87c3bbcd5..53b3e2ec9 100644 --- a/core/libs/prx/libSceFont/src/Unimplemented.cpp +++ b/core/libs/prx/libSceFont/src/Unimplemented.cpp @@ -88,16 +88,6 @@ int APS5_VABI sceFontGetGlyphExpandBufferState() { return 0; } -int APS5_VABI sceFontGetScriptLanguage() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceFontGetTypographicDesign() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceFontGlyphGetAttribute() { NotImplemented_nid_no_patch(__func__); return 0; @@ -368,16 +358,6 @@ int APS5_VABI sceFontGraphicsUpdateShapeFillPlot() { return 0; } -int APS5_VABI sceFontSetScriptLanguage() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceFontSetTypographicDesign() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceFontSupportGlyphs() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/tests/GuestFont.cpp b/core/libs/tests/GuestFont.cpp index eb30bd2a2..f87745e78 100644 --- a/core/libs/tests/GuestFont.cpp +++ b/core/libs/tests/GuestFont.cpp @@ -26,6 +26,10 @@ int APS5_VABI sceFontSupportExternalFonts(FontLibrary, std::uint32_t, std::uint3 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 sceFontSetScriptLanguage(FontHandle, int, int); +int APS5_VABI sceFontGetScriptLanguage(FontHandle, int, int*); +int APS5_VABI sceFontSetTypographicDesign(FontHandle, int, int); +int APS5_VABI sceFontGetTypographicDesign(FontHandle, int, int*); int APS5_VABI sceFontSetResolutionDpi(FontHandle, std::uint32_t, std::uint32_t); int APS5_VABI sceFontGetResolutionDpi(FontHandle, std::uint32_t*, std::uint32_t*); int APS5_VABI sceFontSetScalePixel(FontHandle, float, float); @@ -203,6 +207,17 @@ int main() { const std::vector fontData = EmptyGlyphFont(); Require(sceFontOpenFontMemory(library, fontData.data(), static_cast(fontData.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr); + int setting = -1; + Require(sceFontGetScriptLanguage(font, 3, &setting) == SCE_FONT_OK && setting == 0); + Require(sceFontSetScriptLanguage(font, 3, 7) == SCE_FONT_OK && sceFontSetScriptLanguage(font, 4, 9) == SCE_FONT_OK); + Require(sceFontGetScriptLanguage(font, 3, &setting) == SCE_FONT_OK && setting == 7); + Require(sceFontGetScriptLanguage(font, 4, &setting) == SCE_FONT_OK && setting == 9); + Require(sceFontGetScriptLanguage(font, 3, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + Require(sceFontSetScriptLanguage(nullptr, 3, 7) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + Require(sceFontSetTypographicDesign(font, 1, 2) == SCE_FONT_OK); + Require(sceFontGetTypographicDesign(font, 1, &setting) == SCE_FONT_OK && setting == 2); + Require(sceFontGetTypographicDesign(font, 5, &setting) == SCE_FONT_OK && setting == 0); + Require(sceFontGetTypographicDesign(nullptr, 1, &setting) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); std::uint32_t hDpi = 1; std::uint32_t vDpi = 1; Require(sceFontGetResolutionDpi(font, &hDpi, &vDpi) == SCE_FONT_OK && hDpi == 72 && vDpi == 72); diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 73ac7832e..5c391be32 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -39,6 +39,7 @@ Throughout the project, every function at every stage either **does exactly what - [ulobjmgr](../../core/libs/prx/ulobjmgr/Export.cpp) registers no object: `_sceUlobjmgrRegisterObject` always hands out id 0 and `_sceUlobjmgrUnregisterObject` releases nothing, as shadPS4 does - [libSceHttp](../../core/libs/prx/libSceHttp/Export.cpp) - no request reaches the network, so `sceHttpSetResponseHeaderMaxSize` has no response header to limit, `sceHttpSetRecvBlockSize` (`(int id, u32 blockSize)` as in [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/network/http.h)) no response body to read in blocks and `sceHttpRedirectCacheFlush` no redirect to forget; `sceHttpsUnloadCert` returns success like `sceHttpsLoadCert`, which keeps no certificate; `sceHttpSetRedirectCallback` and `sceHttpSetCookieRecvCallback` accept callbacks that are never called, `sceHttpsSetSslVersion` has no TLS connection to configure and `sceHttpsGetSslError` reports error 0 with detail 0; `sceHttpSetAuthInfoCallback` accepts a callback that is never called, as no server asks for authentication - [sceFontGlyphDefineAttribute](../../core/libs/prx/libSceFont/src/Render.cpp) (libSceFont) checks the glyph and ignores the attribute and its value, whose meaning is unknown. PPSA01325 sets attribute 0x11 to 0 on a glyph from `sceFontGenerateCharGlyph` that it deletes unused, and draws the character with `sceFontRenderCharGlyphImageHorizontal` +- [sceFontSetScriptLanguage, sceFontGetScriptLanguage, sceFontSetTypographicDesign, sceFontGetTypographicDesign](../../core/libs/prx/libSceFont/src/Style.cpp) (libSceFont) - signatures follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Font/SceFont.cs), not confirmed for the PS5. The handle keeps the language set for each script and the feature set for each typographic design and returns them, with 0 for one never set; the console default and its valid ranges are unknown, so any value is accepted. Neither setting changes shaping or rendering yet ### Unknown function info