mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-02 03:00:23 +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;
|
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() {
|
void clearProbeCache() {
|
||||||
Lock lock( mutex );
|
Lock lock( mutex );
|
||||||
probeCache.clear();
|
probeCache.clear();
|
||||||
@@ -777,6 +806,11 @@ void SystemFontResolver::populateFontList() const {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
CFIndex count = CFArrayGetCount( descriptors );
|
CFIndex count = CFArrayGetCount( descriptors );
|
||||||
|
std::shared_ptr<FreeTypeState> ftState = getFTState();
|
||||||
|
if ( !ftState ) {
|
||||||
|
CFRelease( descriptors );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for ( CFIndex i = 0; i < count; ++i ) {
|
for ( CFIndex i = 0; i < count; ++i ) {
|
||||||
CFStringRef familyNameRef = (CFStringRef)CFArrayGetValueAtIndex( descriptors, i );
|
CFStringRef familyNameRef = (CFStringRef)CFArrayGetValueAtIndex( descriptors, i );
|
||||||
@@ -792,8 +826,12 @@ void SystemFontResolver::populateFontList() const {
|
|||||||
CTFontDescriptorRef familyDesc = CTFontDescriptorCreateWithAttributes( queryDict );
|
CTFontDescriptorRef familyDesc = CTFontDescriptorCreateWithAttributes( queryDict );
|
||||||
CFRelease( queryDict );
|
CFRelease( queryDict );
|
||||||
|
|
||||||
CFSetRef mandatoryAttrs = CFSetCreate(
|
// mandatoryAttributes describes which query attributes must match; it is not a list of
|
||||||
kCFAllocatorDefault, (const void**)&kCTFontURLAttribute, 1, &kCFTypeSetCallBacks );
|
// 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 =
|
CFArrayRef matchingDescs =
|
||||||
CTFontDescriptorCreateMatchingFontDescriptors( familyDesc, mandatoryAttrs );
|
CTFontDescriptorCreateMatchingFontDescriptors( familyDesc, mandatoryAttrs );
|
||||||
@@ -822,6 +860,20 @@ void SystemFontResolver::populateFontList() const {
|
|||||||
if ( fontPath.empty() )
|
if ( fontPath.empty() )
|
||||||
continue;
|
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 traits =
|
||||||
(CFDictionaryRef)CTFontDescriptorCopyAttribute( desc, kCTFontTraitsAttribute );
|
(CFDictionaryRef)CTFontDescriptorCopyAttribute( desc, kCTFontTraitsAttribute );
|
||||||
CGFloat weightVal = 0.0;
|
CGFloat weightVal = 0.0;
|
||||||
@@ -857,9 +909,12 @@ void SystemFontResolver::populateFontList() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FontDesc fontDesc;
|
FontDesc fontDesc;
|
||||||
fontDesc.family = familyName;
|
fontDesc.family = matchedFamily;
|
||||||
fontDesc.path = fontPath;
|
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.weight = ctWeightToFontWeight( weightVal );
|
||||||
fontDesc.stretch = ctWidthToFontStretch( widthVal );
|
fontDesc.stretch = ctWidthToFontStretch( widthVal );
|
||||||
fontDesc.italic = ( slantVal > 0.0 );
|
fontDesc.italic = ( slantVal > 0.0 );
|
||||||
|
|||||||
@@ -128,6 +128,24 @@ UTEST( SystemFontResolver, findVerdana ) {
|
|||||||
query.weight = FontWeight::Normal;
|
query.weight = FontWeight::Normal;
|
||||||
query.italic = false;
|
query.italic = false;
|
||||||
FontDesc desc = resolver->resolve( query );
|
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 || \
|
#if EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_BSD || \
|
||||||
EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOS
|
EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOS
|
||||||
if ( resolver->enumerate().size() > 0 ) {
|
if ( resolver->enumerate().size() > 0 ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user