mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
Merge branch 'develop' of github.com:SpartanJ/eepp into develop
This commit is contained in:
@@ -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 ) {
|
||||
|
||||
Reference in New Issue
Block a user