From 13f25c979fe4396e6d5a76bf183341229da2bacd Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Nov 2017 15:00:26 +0100 Subject: [PATCH] macOS/iOS: Fix garbled text under some conditions There seems to be an issue in CoreText which may cause an existing font descriptor to give unreliable results if it refers to one of the system theme fonts. Since we do not know all function calls or events that may trigger this bug, the safe route is to always create fresh font descriptors when creating fonts for these descriptors. The impact on performance should be small, as Qt has its own internal caches. [ChangeLog][macOS/iOS][Text] Fixed an issue where text using one of the system theme fonts would under certain circumstances display random glyphs. Task-number: QTBUG-63476 Change-Id: I9e9b253018c63976345eec1439a6b78de2cab869 --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 24 ++++++++++++++-------- .../fontdatabases/mac/qcoretextfontdatabase_p.h | 4 +++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git x/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm y/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 6347d4d231..237e8a89a5 100644 --- x/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ y/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -416,7 +416,19 @@ extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); template <> QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) { - CTFontDescriptorRef descriptor = static_cast(usrPtr); + QCFType descriptor = QCFType::constructFromGet( + static_cast(usrPtr)); + + // CoreText will sometimes invalidate information in font descriptors that refer + // to system fonts in certain function calls or application states. While the descriptor + // looks the same from the outside, some internal plumbing is different, causing the results + // of creating CTFonts from those descriptors unreliable. The work-around for this + // is to copy the attributes of those descriptors each time we make a new CTFont + // from them instead of referring to the original, as that may trigger the CoreText bug. + if (m_systemFontDescriptors.contains(descriptor)) { + QCFType attributes = CTFontDescriptorCopyAttributes(descriptor); + descriptor = CTFontDescriptorCreateWithAttributes(attributes); + } // Since we do not pass in the destination DPI to CoreText when making // the font, we need to pass in a point size which is scaled to include @@ -427,14 +439,10 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine qreal scaledPointSize = fontDef.pixelSize; CGAffineTransform matrix = qt_transform_from_fontdef(fontDef); - CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); - if (font) { - QFontEngine *engine = new QCoreTextFontEngine(font, fontDef); - CFRelease(font); - return engine; - } + if (QCFType font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix)) + return new QCoreTextFontEngine(font, fontDef); - return NULL; + return nullptr; } #ifndef QT_NO_FREETYPE diff --git x/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h y/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 9612b909f1..e14d1d6e6e 100644 --- x/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ y/qtbase/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -91,12 +91,14 @@ public: QFont *themeFont(QPlatformTheme::Font) const; const QHash &themeFonts() const; +protected: + mutable QSet m_systemFontDescriptors; + private: void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString()); mutable QString defaultFontName; - mutable QSet m_systemFontDescriptors; mutable QHash m_themeFonts; bool m_hasPopulatedAliases; }; -- 2.15.1