feat(font): implement sceFontGetFontGlyphsCount and sceFontGetCharGlyphCode
Report the face's glyph count and the glyph index of a character through the library's driver; the FreeType driver gains its glyphs_count entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
481c85e7c9
commit
34ba33faf7
|
|
@ -230,6 +230,24 @@ void CopyStyleToCache(FontHandleNative* font) {
|
|||
std::memcpy(&font->cached_style.state, &font->style, sizeof(StyleStateBlock));
|
||||
}
|
||||
|
||||
template <typename TCall>
|
||||
int CallOpenFontObject(FontHandle fontHandle, TCall call) {
|
||||
const auto* font = GetNativeFont(fontHandle);
|
||||
if (!font || font->magic != HANDLE_MAGIC) return SCE_FONT_ERROR_INVALID_FONT_HANDLE;
|
||||
auto* library = static_cast<FontLibNative*>(font->library);
|
||||
if (!library || library->magic != LIBRARY_MAGIC) return SCE_FONT_ERROR_INVALID_FONT_HANDLE;
|
||||
if (!library->sys_driver) return SCE_FONT_ERROR_FATAL;
|
||||
const std::uint32_t modeLow = font->flags & 0x0Fu;
|
||||
FontObj* head = nullptr;
|
||||
std::uint32_t lockWord = 0;
|
||||
auto* entry = AcquireFontCtxEntry(FontContext(library, font), font->open_info.ctx_entry_index, modeLow, &head, &lockWord);
|
||||
if (!entry) return SCE_FONT_ERROR_FATAL;
|
||||
FontObj* obj = FindSubFont(head, font->open_info.sub_font_index);
|
||||
const int rc = (lockWord & OPEN_BIT) != 0 && (lockWord & COUNT_MASK) != 0 && obj ? call(*library->sys_driver, obj) : SCE_FONT_ERROR_FATAL;
|
||||
ReleaseFontCtxEntryLock(entry, modeLow, lockWord);
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma GCC visibility push(default)
|
||||
|
|
@ -453,6 +471,29 @@ int APS5_VABI sceFontGetLibrary(FontHandle fontHandle, FontLibrary* pLibrary) {
|
|||
return SCE_FONT_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontGetFontGlyphsCount(FontHandle fontHandle, std::uint32_t* glyphsCount) {
|
||||
if (!glyphsCount) return SCE_FONT_ERROR_INVALID_PARAMETER;
|
||||
*glyphsCount = 0;
|
||||
const int rc = CallOpenFontObject(fontHandle, [&](const SysDriver& driver, FontObj* obj) {
|
||||
if (!driver.glyphs_count) return SCE_FONT_ERROR_FATAL;
|
||||
return driver.glyphs_count(obj, glyphsCount);
|
||||
});
|
||||
if (rc != SCE_FONT_OK) *glyphsCount = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontGetCharGlyphCode(FontHandle fontHandle, std::uint32_t code, std::uint32_t* glyphCode) {
|
||||
if (!glyphCode) return SCE_FONT_ERROR_INVALID_PARAMETER;
|
||||
*glyphCode = 0;
|
||||
const int rc = CallOpenFontObject(fontHandle, [&](const SysDriver& driver, FontObj* obj) {
|
||||
if (!driver.glyph_index) return SCE_FONT_ERROR_FATAL;
|
||||
if (code == 0) return SCE_FONT_ERROR_NO_SUPPORT_CODE;
|
||||
return driver.glyph_index(obj, code, glyphCode);
|
||||
});
|
||||
if (rc != SCE_FONT_OK) *glyphCode = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontBindRenderer(FontHandle fontHandle, FontRenderer renderer) {
|
||||
auto* font = GetNativeFont(fontHandle);
|
||||
std::uint32_t fontLock = 0;
|
||||
|
|
|
|||
|
|
@ -72,16 +72,6 @@ int APS5_VABI sceFontGetAttribute() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontGetCharGlyphCode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontGetFontGlyphsCount() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceFontGetFontGlyphsOutlineProfile() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -295,6 +295,14 @@ int APS5_VABI LibraryGetFaceMetric(FontObj* obj, std::uint32_t metricId, std::ui
|
|||
return SCE_FONT_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI LibraryGetGlyphsCount(FontObj* obj, std::uint32_t* outCount) {
|
||||
if (!obj || !outCount) return SCE_FONT_ERROR_FATAL;
|
||||
const FT_Face face = FaceOf(obj);
|
||||
if (!face || face->num_glyphs < 0) return SCE_FONT_ERROR_FATAL;
|
||||
*outCount = static_cast<std::uint32_t>(face->num_glyphs);
|
||||
return SCE_FONT_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI LibraryGetGlyphIndex(FontObj* obj, std::uint32_t codepoint, std::uint32_t* outGlyphIndex) {
|
||||
if (!obj || !outGlyphIndex) return SCE_FONT_ERROR_FATAL;
|
||||
const FT_Face face = FaceOf(obj);
|
||||
|
|
@ -735,6 +743,7 @@ SysDriver MakeDriverTable() {
|
|||
driver.close = &LibraryCloseFont;
|
||||
driver.scale = &LibraryGetFaceScale;
|
||||
driver.metric = &LibraryGetFaceMetric;
|
||||
driver.glyphs_count = &LibraryGetGlyphsCount;
|
||||
driver.glyph_index = &LibraryGetGlyphIndex;
|
||||
driver.set_char_with_dpi = &LibrarySetCharSizeWithDpi;
|
||||
driver.set_char_default_dpi = &LibrarySetCharSizeDefaultDpi;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ int APS5_VABI sceFontUnbindRenderer(FontHandle);
|
|||
int APS5_VABI sceFontSetupRenderScalePixel(FontHandle, float, float);
|
||||
int APS5_VABI sceFontSetupRenderScalePoint(FontHandle, float, float);
|
||||
int APS5_VABI sceFontGetKerning(FontHandle, std::uint32_t, std::uint32_t, FontKerning*);
|
||||
int APS5_VABI sceFontGetFontGlyphsCount(FontHandle, std::uint32_t*);
|
||||
int APS5_VABI sceFontGetCharGlyphCode(FontHandle, std::uint32_t, std::uint32_t*);
|
||||
int APS5_VABI sceFontGetRenderScaledKerning(FontHandle, std::uint32_t, std::uint32_t, FontKerning*);
|
||||
const void* APS5_VABI sceFontSelectLibraryFt(int);
|
||||
const void* APS5_VABI sceFontSelectRendererFt(int);
|
||||
|
|
@ -171,6 +173,20 @@ int main() {
|
|||
hDpi = 1;
|
||||
vDpi = 1;
|
||||
Require(sceFontGetResolutionDpi(&unopened, &hDpi, &vDpi) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && hDpi == 0 && vDpi == 0);
|
||||
std::uint32_t glyphsCount = 0;
|
||||
Require(sceFontGetFontGlyphsCount(font, &glyphsCount) == SCE_FONT_OK && glyphsCount == 1);
|
||||
Require(sceFontGetFontGlyphsCount(font, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER);
|
||||
glyphsCount = 1;
|
||||
Require(sceFontGetFontGlyphsCount(nullptr, &glyphsCount) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && glyphsCount == 0);
|
||||
glyphsCount = 1;
|
||||
Require(sceFontGetFontGlyphsCount(&unopened, &glyphsCount) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && glyphsCount == 0);
|
||||
std::uint32_t glyphCode = 1;
|
||||
Require(sceFontGetCharGlyphCode(font, 'A', &glyphCode) == SCE_FONT_ERROR_NO_SUPPORT_GLYPH && glyphCode == 0);
|
||||
Require(sceFontGetCharGlyphCode(font, 'A', nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER);
|
||||
glyphCode = 1;
|
||||
Require(sceFontGetCharGlyphCode(nullptr, 'A', &glyphCode) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && glyphCode == 0);
|
||||
glyphCode = 1;
|
||||
Require(sceFontGetCharGlyphCode(&unopened, 'A', &glyphCode) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && glyphCode == 0);
|
||||
Require(sceFontCloseFont(font) == SCE_FONT_OK);
|
||||
|
||||
FontRenderer renderer = nullptr;
|
||||
|
|
@ -179,6 +195,13 @@ int main() {
|
|||
const std::vector<unsigned char> kerningData = KerningFont();
|
||||
font = nullptr;
|
||||
Require(sceFontOpenFontMemory(library, kerningData.data(), static_cast<std::uint32_t>(kerningData.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr);
|
||||
Require(sceFontGetFontGlyphsCount(font, &glyphsCount) == SCE_FONT_OK && glyphsCount == 3);
|
||||
Require(sceFontGetCharGlyphCode(font, 'A', &glyphCode) == SCE_FONT_OK && glyphCode == 1);
|
||||
Require(sceFontGetCharGlyphCode(font, 'V', &glyphCode) == SCE_FONT_OK && glyphCode == 2);
|
||||
glyphCode = 1;
|
||||
Require(sceFontGetCharGlyphCode(font, 'B', &glyphCode) == SCE_FONT_ERROR_NO_SUPPORT_GLYPH && glyphCode == 0);
|
||||
glyphCode = 1;
|
||||
Require(sceFontGetCharGlyphCode(font, 0, &glyphCode) == SCE_FONT_ERROR_NO_SUPPORT_CODE && glyphCode == 0);
|
||||
Require(sceFontSetResolutionDpi(font, 144, 144) == SCE_FONT_OK);
|
||||
Require(sceFontSetScalePixel(font, 100.0f, 100.0f) == SCE_FONT_OK);
|
||||
FontKerning kerning{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [AMPR markers](../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) - signatures taken from the [ampr_emu](https://github.com/drakmor/ampr_emu) reimplementation, not confirmed on a title: `sceAmprCommandBufferSetMarkerWithColor` takes the color by pointer, the push and measure variants by value. Colors are not recorded
|
||||
- [sceFontGetRenderScaledKerning](../../core/libs/prx/libSceFont/src/Render.cpp) (libSceFont) - arguments, the cleared output and the bound renderer check taken from `cellFontGetRenderScaledKerning` in [RPCS3](https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/cellFont.cpp) (PS3 predecessor of the library), not confirmed on a title. The kerning is the `sceFontGetKerning` one at the render scale
|
||||
- [sceFontGetPixelResolution](../../core/libs/prx/libSceFont/src/Library.cpp) (libSceFont) - signature taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json), not confirmed on a title. The value is the one the library's driver reports (64 for FreeType); the argument checks and the cleared output follow `sceFontGetLibrary`
|
||||
- [sceFontGetFontGlyphsCount, sceFontGetCharGlyphCode](../../core/libs/prx/libSceFont/src/Open.cpp) (libSceFont) - signatures taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json), not confirmed on a title. The count is the face's glyph count and the glyph code its glyph index, as the library's driver reports them; a code with no glyph returns `NO_SUPPORT_GLYPH` and code 0 `NO_SUPPORT_CODE`, as `sceFontRenderCharGlyphImage` does. The argument checks and the cleared output follow `sceFontGetPixelResolution`
|
||||
- [sceFontCreateWritingLine, sceFontWritingLineWritesOrder](../../core/libs/prx/libSceFont/src/WritingLine.cpp) (libSceFont) - signatures and the `SceFontWritingLineStep`/`SceFontCreateWritingLineDetail` layouts (detail id `0x0FD5`) taken from [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Font/SceFontStructs.cs), not confirmed on a title; the meaning of the 64-bit writing attribute is unknown
|
||||
- [sceSaveDataTransferringMountPs4, sceSaveDataDirNameSearchPs4](../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native) - arguments assumed to be those of `sceSaveDataTransferringMount` and `sceSaveDataDirNameSearch`: KytyPS5 binds both NIDs to the PS5 functions, and [prosper](https://github.com/mattias800/prosper) captured the same result layout on a title for the search. There is no PS4 save area, so the mount returns `NOT_FOUND` and the search reports zero hits
|
||||
- [sceAgcSetSubmitMode](../../core/libs/prx/libSceAgc/Misc/src/Suspend.cpp) (libSceAgc) - mode values unknown; only 0 is accepted
|
||||
|
|
|
|||
Loading…
Reference in New Issue