Merge branch 'develop' of github.com:SpartanJ/eepp into develop

This commit is contained in:
Martín Lucas Golini
2026-08-17 22:43:00 -03:00
2 changed files with 77 additions and 4 deletions
+59 -4
View File
@@ -137,6 +137,35 @@ struct FreeTypeState {
return found;
}
bool findFaceIndex( const std::string& path, const std::string& postScriptName,
EE::Uint32& faceIndex ) {
Lock lock( mutex );
FT_Face face{ nullptr };
if ( !library || FT_New_Face( library, path.c_str(), -1, &face ) != 0 )
return false;
const FT_Long numFaces = face->num_faces;
FT_Done_Face( face );
if ( numFaces == 1 ) {
faceIndex = 0;
return true;
}
if ( postScriptName.empty() )
return false;
for ( FT_Long i = 0; i < numFaces; ++i ) {
if ( FT_New_Face( library, path.c_str(), i, &face ) != 0 )
continue;
const char* facePostScriptName = FT_Get_Postscript_Name( face );
const bool matches = facePostScriptName && postScriptName == facePostScriptName;
FT_Done_Face( face );
if ( matches ) {
faceIndex = static_cast<EE::Uint32>( i );
return true;
}
}
return false;
}
void clearProbeCache() {
Lock lock( mutex );
probeCache.clear();
@@ -777,6 +806,11 @@ void SystemFontResolver::populateFontList() const {
return;
CFIndex count = CFArrayGetCount( descriptors );
std::shared_ptr<FreeTypeState> ftState = getFTState();
if ( !ftState ) {
CFRelease( descriptors );
return;
}
for ( CFIndex i = 0; i < count; ++i ) {
CFStringRef familyNameRef = (CFStringRef)CFArrayGetValueAtIndex( descriptors, i );
@@ -792,8 +826,12 @@ void SystemFontResolver::populateFontList() const {
CTFontDescriptorRef familyDesc = CTFontDescriptorCreateWithAttributes( queryDict );
CFRelease( queryDict );
CFSetRef mandatoryAttrs = CFSetCreate(
kCFAllocatorDefault, (const void**)&kCTFontURLAttribute, 1, &kCFTypeSetCallBacks );
// mandatoryAttributes describes which query attributes must match; it is not a list of
// attributes to return. Requiring the URL (which is absent from the query) lets CoreText
// substitute Helvetica for families such as Verdana.
CFSetRef mandatoryAttrs =
CFSetCreate( kCFAllocatorDefault, (const void**)&kCTFontFamilyNameAttribute, 1,
&kCFTypeSetCallBacks );
CFArrayRef matchingDescs =
CTFontDescriptorCreateMatchingFontDescriptors( familyDesc, mandatoryAttrs );
@@ -822,6 +860,20 @@ void SystemFontResolver::populateFontList() const {
if ( fontPath.empty() )
continue;
CFStringRef postScriptNameRef =
(CFStringRef)CTFontDescriptorCopyAttribute( desc, kCTFontNameAttribute );
std::string postScriptName = cfStringToStd( postScriptNameRef );
if ( postScriptNameRef )
CFRelease( postScriptNameRef );
CFStringRef matchedFamilyRef =
(CFStringRef)CTFontDescriptorCopyAttribute( desc, kCTFontFamilyNameAttribute );
std::string matchedFamily = cfStringToStd( matchedFamilyRef );
if ( matchedFamilyRef )
CFRelease( matchedFamilyRef );
if ( normalizeFamily( matchedFamily ) != normalizeFamily( familyName ) )
continue;
CFDictionaryRef traits =
(CFDictionaryRef)CTFontDescriptorCopyAttribute( desc, kCTFontTraitsAttribute );
CGFloat weightVal = 0.0;
@@ -857,9 +909,12 @@ void SystemFontResolver::populateFontList() const {
}
FontDesc fontDesc;
fontDesc.family = familyName;
fontDesc.family = matchedFamily;
fontDesc.path = fontPath;
fontDesc.faceIndex = static_cast<Uint32>( j );
// j is only the descriptor's position in matchingDescs and is unrelated to the face's
// index inside a TTC. Match CoreText's PostScript name against the actual file faces.
if ( !ftState->findFaceIndex( fontPath, postScriptName, fontDesc.faceIndex ) )
continue;
fontDesc.weight = ctWeightToFontWeight( weightVal );
fontDesc.stretch = ctWidthToFontStretch( widthVal );
fontDesc.italic = ( slantVal > 0.0 );
@@ -128,6 +128,24 @@ UTEST( SystemFontResolver, findVerdana ) {
query.weight = FontWeight::Normal;
query.italic = false;
FontDesc desc = resolver->resolve( query );
#if EE_PLATFORM == EE_PLATFORM_MACOS
auto verdanaFaces = resolver->enumerateFamily( "Verdana" );
if ( !verdanaFaces.empty() ) {
EXPECT_FALSE( desc.path.empty() );
EXPECT_STDSTREQ( "Verdana", desc.family );
EXPECT_TRUE_MSG(
desc.path.find( "Verdana" ) != std::string::npos,
( "Verdana must not resolve through a substituted CoreText family: " + desc.path )
.c_str() );
for ( const FontDesc& face : verdanaFaces ) {
FontTrueTypePtr font = defaultResourceScope().getFontService().loadSystemFont( face );
EXPECT_TRUE_MSG(
font && font->loaded(),
( "CoreText face index must load the selected Verdana face: " + face.getFileKey() )
.c_str() );
}
}
#endif
#if EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_BSD || \
EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOS
if ( resolver->enumerate().size() > 0 ) {