From b22c4e593b99675a641fd6403a70ad9974b02508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 24 Nov 2018 22:50:16 +0100 Subject: CoreText: Localize getTraitValue helper function It's only used in a single function (twice), so let's keep it closer to the call site. Change-Id: I7f8ceadc380171237eef3fa6b03ccd6bc89e99af Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 0430e79bac..c00b9c3d46 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -155,17 +155,6 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont, } } -static float getTraitValue(CFDictionaryRef allTraits, CFStringRef trait) -{ - if (CFDictionaryContainsKey(allTraits, trait)) { - CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait); - float v = 0; - CFNumberGetValue(traitNum, kCFNumberFloatType, &v); - return v; - } - return 0; -} - int QCoreTextFontEngine::antialiasingThreshold = 0; QFontEngine::GlyphFormat QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A32; @@ -277,6 +266,16 @@ void QCoreTextFontEngine::init() if (traits & kCTFontItalicTrait) fontDef.style = QFont::StyleItalic; + static const auto getTraitValue = [](CFDictionaryRef allTraits, CFStringRef trait) -> float { + if (CFDictionaryContainsKey(allTraits, trait)) { + CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait); + float v = 0; + CFNumberGetValue(traitNum, kCFNumberFloatType, &v); + return v; + } + return 0; + }; + CFDictionaryRef allTraits = CTFontCopyTraits(ctfont); fontDef.weight = QCoreTextFontEngine::qtWeightFromCFWeight(getTraitValue(allTraits, kCTFontWeightTrait)); int slant = static_cast(getTraitValue(allTraits, kCTFontSlantTrait) * 500 + 500); -- cgit v1.2.3 From 9dd2048c1a11b29f0e16a7906e216133201d24db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 24 Nov 2018 23:15:07 +0100 Subject: CoreText: Simplify and share code for loading glyph advances The function doesn't need the flags argument, nor does it need the ctfont or fontdef arguments if it's a normal const member function. It can also be used from QCoreTextFontEngine::stringToCMap(), instead of duplicating the code. This was originally the case before b4aa5d97 which improved surrogate pair handling, but for some reason the change introduced the duplicate code instead of just changing the arguments in the function call slightly. The use of 0xff000000 to skip certain glyphs looks dubious, and is probably related to QFontEngineMulti's use of the high byte to indicate which engine the glyph came from, but the multi engine strips this away before calling out to the concrete engine so it could potentially be removed in a later patch. Change-Id: I6c693595616da1b69fdbe3d7a31e392a8443369d Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 65 +++++++++------------- .../fontdatabases/mac/qfontengine_coretext_p.h | 2 + 2 files changed, 27 insertions(+), 40 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index c00b9c3d46..a58ea71b19 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -133,28 +133,6 @@ QFont::Weight QCoreTextFontEngine::qtWeightFromCFWeight(float value) return ret; } -static void loadAdvancesForGlyphs(CTFontRef ctfont, - QVarLengthArray &cgGlyphs, - QGlyphLayout *glyphs, int len, - QFontEngine::ShaperFlags flags, - const QFontDef &fontDef) -{ - Q_UNUSED(flags); - QVarLengthArray advances(len); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), len); - - for (int i = 0; i < len; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - continue; - glyphs->advances[i] = QFixed::fromReal(advances[i].width); - } - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < len; ++i) - glyphs->advances[i] = glyphs->advances[i].round(); - } -} - int QCoreTextFontEngine::antialiasingThreshold = 0; QFontEngine::GlyphFormat QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A32; @@ -360,22 +338,9 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout * *nglyphs = glyph_pos; glyphs->numGlyphs = glyph_pos; - if (flags & GlyphIndicesOnly) - return true; - - QVarLengthArray advances(glyph_pos); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), glyph_pos); - - for (int i = 0; i < glyph_pos; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - continue; - glyphs->advances[i] = QFixed::fromReal(advances[i].width); - } + if (!(flags & GlyphIndicesOnly)) + loadAdvancesForGlyphs(cgGlyphs, glyphs); - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < glyph_pos; ++i) - glyphs->advances[i] = glyphs->advances[i].round(); - } return true; } @@ -801,17 +766,37 @@ QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPositio void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const { - int i, numGlyphs = glyphs->numGlyphs; + Q_UNUSED(flags); + + const int numGlyphs = glyphs->numGlyphs; QVarLengthArray cgGlyphs(numGlyphs); - for (i = 0; i < numGlyphs; ++i) { + for (int i = 0; i < numGlyphs; ++i) { if (glyphs->glyphs[i] & 0xff000000) cgGlyphs[i] = 0; else cgGlyphs[i] = glyphs->glyphs[i]; } - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef); + loadAdvancesForGlyphs(cgGlyphs, glyphs); +} + +void QCoreTextFontEngine::loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const +{ + const int numGlyphs = glyphs->numGlyphs; + QVarLengthArray advances(numGlyphs); + CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), numGlyphs); + + for (int i = 0; i < numGlyphs; ++i) { + if (glyphs->glyphs[i] & 0xff000000) + continue; + glyphs->advances[i] = QFixed::fromReal(advances[i].width); + } + + if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { + for (int i = 0; i < numGlyphs; ++i) + glyphs->advances[i] = glyphs->advances[i].round(); + } } QFontEngine::FaceId QCoreTextFontEngine::faceId() const diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index b77aaa27c1..f4213a2ffa 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -128,6 +128,8 @@ public: protected: void init(); QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); + void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; + CTFontRef ctfont; CGFontRef cgFont; int synthesisFlags; -- cgit v1.2.3 From 61a94d2d046c1448ba4c66dfc8e0246286bab14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 24 Nov 2018 23:42:32 +0100 Subject: CoreText: Share code by using delegate constructor Change-Id: If3d5d533f98552335517ef61cb748d0117fe3053 Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 15 +++++++++------ .../fontdatabases/mac/qfontengine_coretext_p.h | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index a58ea71b19..b5e4359caf 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -190,10 +190,8 @@ QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, qre } QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) - : QFontEngine(Mac) + : QCoreTextFontEngine(def) { - fontDef = def; - transform = qt_transform_from_fontdef(fontDef); ctfont = font; CFRetain(ctfont); cgFont = CTFontCopyGraphicsFont(font, NULL); @@ -201,10 +199,8 @@ QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) } QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) - : QFontEngine(Mac) + : QCoreTextFontEngine(def) { - fontDef = def; - transform = qt_transform_from_fontdef(fontDef); cgFont = font; // Keep reference count balanced CFRetain(cgFont); @@ -212,6 +208,13 @@ QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) init(); } +QCoreTextFontEngine::QCoreTextFontEngine(const QFontDef &def) + : QFontEngine(Mac) +{ + fontDef = def; + transform = qt_transform_from_fontdef(fontDef); +} + QCoreTextFontEngine::~QCoreTextFontEngine() { CFRelease(cgFont); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index f4213a2ffa..33c3c0cd40 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -126,6 +126,7 @@ public: static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); protected: + QCoreTextFontEngine(const QFontDef &def); void init(); QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; -- cgit v1.2.3 From d3ec5a2b09f3c9f5a67e757aa6b7b0dd09bbe97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 00:41:00 +0100 Subject: CoreText: Use QCFType to track CoreFoundation member variables The operator T() function of QAppleRefCounted should be const so that the underlying type can be accessed from const member functions just like the naked underlying type could. Change-Id: I0819c5795d28442a6ff4db2732e211b183574f9f Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 19 +++++++------------ .../fontdatabases/mac/qfontengine_coretext_p.h | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index b5e4359caf..2fba47d5dd 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -192,19 +192,16 @@ QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, qre QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) : QCoreTextFontEngine(def) { - ctfont = font; - CFRetain(ctfont); - cgFont = CTFontCopyGraphicsFont(font, NULL); + ctfont = QCFType::constructFromGet(font); + cgFont = CTFontCopyGraphicsFont(font, nullptr); init(); } QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) : QCoreTextFontEngine(def) { - cgFont = font; - // Keep reference count balanced - CFRetain(cgFont); - ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, NULL); + cgFont = QCFType::constructFromGet(font); + ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, nullptr); init(); } @@ -217,14 +214,12 @@ QCoreTextFontEngine::QCoreTextFontEngine(const QFontDef &def) QCoreTextFontEngine::~QCoreTextFontEngine() { - CFRelease(cgFont); - CFRelease(ctfont); } void QCoreTextFontEngine::init() { - Q_ASSERT(ctfont != NULL); - Q_ASSERT(cgFont != NULL); + Q_ASSERT(ctfont); + Q_ASSERT(cgFont); face_id.index = 0; QCFString name = CTFontCopyName(ctfont, kCTFontUniqueNameKey); @@ -856,7 +851,7 @@ QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const Qt::HANDLE QCoreTextFontEngine::handle() const { - return (Qt::HANDLE)ctfont; + return (Qt::HANDLE)(static_cast(ctfont)); } bool QCoreTextFontEngine::supportsTransformation(const QTransform &transform) const diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 33c3c0cd40..7ed2faff8e 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -131,8 +131,8 @@ protected: QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; - CTFontRef ctfont; - CGFontRef cgFont; + QCFType ctfont; + QCFType cgFont; int synthesisFlags; CGAffineTransform transform; QFixed avgCharWidth; -- cgit v1.2.3 From 5fd6f4d8824b51cfdb05b4dd918db04941366ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 14:00:58 +0100 Subject: CoreText: Use QCFType instead of manual release/retain Change-Id: I4925ec0e563e784f542fd44706a214771c6abd2b Reviewed-by: Simon Hausmann --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 2fba47d5dd..fbd2f81b19 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -252,12 +252,11 @@ void QCoreTextFontEngine::init() return 0; }; - CFDictionaryRef allTraits = CTFontCopyTraits(ctfont); + QCFType allTraits = CTFontCopyTraits(ctfont); fontDef.weight = QCoreTextFontEngine::qtWeightFromCFWeight(getTraitValue(allTraits, kCTFontWeightTrait)); int slant = static_cast(getTraitValue(allTraits, kCTFontSlantTrait) * 500 + 500); if (slant > 500 && !(traits & kCTFontItalicTrait)) fontDef.style = QFont::StyleOblique; - CFRelease(allTraits); if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) synthesisFlags |= SynthesizedBold; @@ -647,13 +646,13 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition #endif im.fill(0); // Faster than Qt::black - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + QCFType colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); uint cgflags = isColorGlyph ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version cgflags |= kCGBitmapByteOrder32Host; #endif - CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), + QCFType ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, cgflags); Q_ASSERT(ctx); @@ -706,9 +705,6 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); } - CGContextRelease(ctx); - CGColorSpaceRelease(colorspace); - #if defined(Q_OS_MACOS) if (blackOnWhiteGlyphs) im.invertPixels(); -- cgit v1.2.3 From 09e3457541c54b084365bfb77ad58474f0666374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 14:09:00 +0100 Subject: macOS: Share code for resolving CGImage bitmapInfor for a QImage Removes assumptions about QImage format in a few places. Change-Id: I515701be53190429a48956c31986fa0804806406 Reviewed-by: Simon Hausmann --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index fbd2f81b19..e4ee0c0ac4 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -45,7 +45,7 @@ #include #endif #include - +#include #include #include @@ -647,14 +647,9 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition im.fill(0); // Faster than Qt::black QCFType colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - uint cgflags = isColorGlyph ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - QCFType ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, - cgflags); + qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); CGContextSetFontSize(ctx, fontDef.pixelSize); const bool antialias = (aa || fontDef.pointSize > antialiasingThreshold) && !(fontDef.styleStrategy & QFont::NoAntialias); -- cgit v1.2.3 From d4e3442fdbb98b5c635448031ff9958819a46bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 15:59:04 +0100 Subject: CoreText: Modernize font smoothing and antialiasing threshold detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The way macOS does font smoothing has changed in Mojave, and we need to take both this new algorithm into account, as well as support users who set legacy preferences to revert back to subpixel font smoothing. As a followup to this patch we will tweak some of the existing logic to take the new font smoothing algorithm into account, so this is just a first step. Change-Id: If37014c18515f406b8bb8194c9df7a75c2eb10fc Reviewed-by: Simon Hausmann Reviewed-by: Tor Arne Vestbø Reviewed-by: Allan Sandfeld Jensen --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 65 ----------- .../fontdatabases/mac/qfontengine_coretext.mm | 125 ++++++++++++++++++++- .../fontdatabases/mac/qfontengine_coretext_p.h | 15 ++- 3 files changed, 131 insertions(+), 74 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 3718ebdda6..ba23271e55 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -117,71 +117,6 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context) QCoreTextFontDatabase::QCoreTextFontDatabase() : m_hasPopulatedAliases(false) { -#ifdef Q_OS_MACX - /* - font_smoothing = 0 means no smoothing, while 1-3 means subpixel - antialiasing with different hinting styles (but we don't care about the - exact value, only if subpixel rendering is available or not) - */ - int font_smoothing = 0; - -#if QT_CONFIG(settings) - QSettings appleSettings(QLatin1String("apple.com")); - QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold")); - if (appleValue.isValid()) - QCoreTextFontEngine::antialiasingThreshold = appleValue.toInt(); - - appleValue = appleSettings.value(QLatin1String("AppleFontSmoothing")); - if (appleValue.isValid()) { - font_smoothing = appleValue.toInt(); - } else -#endif // settings - { - // non-Apple displays do not provide enough information about subpixel rendering so - // draw text with cocoa and compare pixel colors to see if subpixel rendering is enabled - int w = 10; - int h = 10; - NSRect rect = NSMakeRect(0.0, 0.0, w, h); - NSImage *fontImage = [[NSImage alloc] initWithSize:NSMakeSize(w, h)]; - - [fontImage lockFocus]; - - [[NSColor whiteColor] setFill]; - NSRectFill(rect); - - NSString *str = @"X\\"; - NSFont *font = [NSFont fontWithName:@"Helvetica" size:10.0]; - NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; - [attrs setObject:font forKey:NSFontAttributeName]; - [attrs setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName]; - - [str drawInRect:rect withAttributes:attrs]; - - NSBitmapImageRep *nsBitmapImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect]; - - [fontImage unlockFocus]; - - float red, green, blue; - for (int x = 0; x < w; x++) { - for (int y = 0; y < h; y++) { - NSColor *pixelColor = [nsBitmapImage colorAtX:x y:y]; - red = [pixelColor redComponent]; - green = [pixelColor greenComponent]; - blue = [pixelColor blueComponent]; - if (red != green || red != blue) - font_smoothing = 1; - } - } - - [nsBitmapImage release]; - [fontImage release]; - } - QCoreTextFontEngine::defaultGlyphFormat = (font_smoothing > 0 - ? QFontEngine::Format_A32 - : QFontEngine::Format_A8); -#else - QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A8; -#endif } QCoreTextFontDatabase::~QCoreTextFontDatabase() diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index e4ee0c0ac4..d939ee1b24 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -85,6 +85,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts") + static float SYNTHETIC_ITALIC_SKEW = std::tan(14.f * std::acos(0.f) / 90.f); bool QCoreTextFontEngine::ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) @@ -133,9 +135,6 @@ QFont::Weight QCoreTextFontEngine::qtWeightFromCFWeight(float value) return ret; } -int QCoreTextFontEngine::antialiasingThreshold = 0; -QFontEngine::GlyphFormat QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A32; - CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef) { CGAffineTransform transform = CGAffineTransformIdentity; @@ -236,8 +235,10 @@ void QCoreTextFontEngine::init() if (traits & kCTFontColorGlyphsTrait) glyphFormat = QFontEngine::Format_ARGB; + else if (fontSmoothing() == FontSmoothing::Subpixel) + glyphFormat = QFontEngine::Format_A32; else - glyphFormat = defaultGlyphFormat; + glyphFormat = QFontEngine::Format_A8; if (traits & kCTFontItalicTrait) fontDef.style = QFont::StyleItalic; @@ -520,7 +521,7 @@ static void convertCGPathToQPainterPath(void *info, const CGPathElement *element myInfo->path->closeSubpath(); break; default: - qDebug() << "Unhandled path transform type: " << element->type; + qCWarning(lcQpaFonts) << "Unhandled path transform type: " << element->type; } } @@ -608,6 +609,118 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s return br; } +int QCoreTextFontEngine::antialiasingThreshold() +{ + static const int antialiasingThreshold = [] { + auto defaults = [NSUserDefaults standardUserDefaults]; + int threshold = [defaults integerForKey:@"AppleAntiAliasingThreshold"]; + qCDebug(lcQpaFonts) << "Resolved antialiasing threshold. Defaults =" + << [[defaults dictionaryRepresentation] dictionaryWithValuesForKeys:@[ + @"AppleAntiAliasingThreshold" + ]] << "Result =" << threshold; + return threshold; + }(); + return antialiasingThreshold; +} + +/* + Apple has gone through many iterations of its font smoothing algorithms, + and there are many ways to enable or disable certain aspects of it. As + keeping up with all the different toggles and behavior differences between + macOS versions is tricky, we resort to rendering a single glyph in a few + configurations, picking up the font smoothing algorithm from the observed + result. + + The possible values are: + + - Disabled: No font smoothing is applied. + + Possibly triggered by the user unchecking the "Use font smoothing when + available" checkbox in the system preferences or setting AppleFontSmoothing + to 0. Also controlled by the CGContextSetAllowsFontSmoothing() API, + which gets its default from the settings above. This API overrides + the more granular CGContextSetShouldSmoothFonts(), which we use to + enable (request) or disable font smoothing. + + Note that this does not exclude normal antialiasing, controlled by + the CGContextSetShouldAntialias() API. + + - Subpixel: Font smoothing is applied, and affects subpixels. + + This was the default mode on macOS versions prior to 10.14 (Mojave). + The font dilation (stem darkening) parameters were controlled by the + AppleFontSmoothing setting, ranging from 1 to 3 (light to strong). + + On Mojave it is no longer supported, but can be triggered by a legacy + override (CGFontRenderingFontSmoothingDisabled=NO), so we need to + still account for it, otherwise users will have a bad time. + + - Grayscale: Font smoothing is applied, but does not affect subpixels. + + This is the default mode on macOS 10.14 (Mojave). The font dilation + (stem darkening) parameters are not affected by the AppleFontSmoothing + setting, but are instead computed based on the fill color used when + drawing the glyphs (white fill gives a lighter dilation than black + fill). This affects how we build our glyph cache, since we produce + alpha maps by drawing white on black. +*/ +QCoreTextFontEngine::FontSmoothing QCoreTextFontEngine::fontSmoothing() +{ + static const FontSmoothing cachedFontSmoothing = [] { + static const int kSize = 10; + QCFType font = CTFontCreateWithName(CFSTR("Helvetica"), kSize, nullptr); + + UniChar character('X'); CGGlyph glyph; + CTFontGetGlyphsForCharacters(font, &character, &glyph, 1); + + auto drawGlyph = [&](bool smooth) -> QImage { + QImage image(kSize, kSize, QImage::Format_RGB32); + image.fill(0); + + QMacCGContext ctx(&image); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetGrayFillColor(ctx, 1, 1); + + // Will be ignored if CGContextSetAllowsFontSmoothing() has been + // set to false by CoreGraphics based on user defaults. + CGContextSetShouldSmoothFonts(ctx, smooth); + + CTFontDrawGlyphs(font, &glyph, &CGPointZero, 1, ctx); + return image; + }; + + QImage nonSmoothed = drawGlyph(false); + QImage smoothed = drawGlyph(true); + + FontSmoothing fontSmoothing = FontSmoothing::Disabled; + [&] { + for (int x = 0; x < kSize; ++x) { + for (int y = 0; y < kSize; ++y) { + QRgb sp = smoothed.pixel(x, y); + if (qRed(sp) != qGreen(sp) || qRed(sp) != qBlue(sp)) { + fontSmoothing = FontSmoothing::Subpixel; + return; + } + + if (sp != nonSmoothed.pixel(x, y)) + fontSmoothing = FontSmoothing::Grayscale; + } + } + }(); + + auto defaults = [NSUserDefaults standardUserDefaults]; + qCDebug(lcQpaFonts) << "Resolved font smoothing algorithm. Defaults =" + << [[defaults dictionaryRepresentation] dictionaryWithValuesForKeys:@[ + @"AppleFontSmoothing", + @"CGFontRenderingFontSmoothingDisabled" + ]] << "Result =" << fontSmoothing; + + return fontSmoothing; + }(); + + return cachedFontSmoothing; +} + bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const { // Only works well when font-smoothing is enabled @@ -652,7 +765,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); CGContextSetFontSize(ctx, fontDef.pixelSize); - const bool antialias = (aa || fontDef.pointSize > antialiasingThreshold) && !(fontDef.styleStrategy & QFont::NoAntialias); + const bool antialias = (aa || fontDef.pointSize > antialiasingThreshold()) && !(fontDef.styleStrategy & QFont::NoAntialias); CGContextSetShouldAntialias(ctx, antialias); const bool smoothing = antialias && !(fontDef.styleStrategy & QFont::NoSubpixelAntialias); CGContextSetShouldSmoothFonts(ctx, smoothing); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 7ed2faff8e..2ce46a4706 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -53,6 +53,7 @@ #include #include +#include #ifdef Q_OS_OSX #include @@ -63,8 +64,12 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts) + class QCoreTextFontEngine : public QFontEngine { + Q_GADGET + public: QCoreTextFontEngine(CTFontRef font, const QFontDef &def); QCoreTextFontEngine(CGFontRef font, const QFontDef &def); @@ -118,13 +123,17 @@ public: QFontEngine::Properties properties() const override; + enum FontSmoothing { Disabled, Subpixel, Grayscale }; + Q_ENUM(FontSmoothing); + + static FontSmoothing fontSmoothing(); + static int antialiasingThreshold(); + static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length); static QFont::Weight qtWeightFromCFWeight(float value); - static int antialiasingThreshold; - static QFontEngine::GlyphFormat defaultGlyphFormat; - static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); + protected: QCoreTextFontEngine(const QFontDef &def); void init(); -- cgit v1.2.3 From 6b93b01ad6dfb5b0b2f067462690bdf14668f96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 16:22:30 +0100 Subject: CoreText: Add helper function to determine if a font has color glyphs Makes for clearer code than looking at the glyph format. Change-Id: Id6dd2a7851aac2a42cc27d9e2fb408ce9a5345d3 Reviewed-by: Simon Hausmann Reviewed-by: Allan Sandfeld Jensen --- .../fontdatabases/mac/qfontengine_coretext.mm | 16 ++++++++++------ .../fontdatabases/mac/qfontengine_coretext_p.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index d939ee1b24..91d3d811b5 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -433,6 +433,11 @@ qreal QCoreTextFontEngine::maxCharWidth() const return bb.xoff.toReal(); } +bool QCoreTextFontEngine::hasColorGlyphs() const +{ + return glyphFormat == QFontEngine::Format_ARGB; +} + void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) { QVarLengthArray positions; @@ -529,7 +534,7 @@ static void convertCGPathToQPainterPath(void *info, const CGPathElement *element void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs, QPainterPath *path, QTextItem::RenderFlags) { - if (glyphFormat == QFontEngine::Format_ARGB) + if (hasColorGlyphs()) return; // We can't convert color-glyphs to path CGAffineTransform cgMatrix = CGAffineTransformIdentity; @@ -731,8 +736,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition { glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); - bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB; - QImage::Format imageFormat = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; + QImage::Format imageFormat = hasColorGlyphs() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; QImage im(br.width.ceil().toInt(), br.height.ceil().toInt(), imageFormat); if (!im.width() || !im.height()) return im; @@ -751,7 +755,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition if (!qt_mac_applicationIsInDarkMode()) glyphColor = CGColorGetConstantColor(kCGColorBlack); } - const bool blackOnWhiteGlyphs = !isColorGlyph + const bool blackOnWhiteGlyphs = !hasColorGlyphs() && CGColorEqualToColor(glyphColor, CGColorGetConstantColor(kCGColorBlack)); if (blackOnWhiteGlyphs) im.fill(Qt::white); @@ -775,7 +779,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - if (!isColorGlyph) // CTFontDrawGlyphs incorporates the font's matrix already + if (!hasColorGlyphs()) // CTFontDrawGlyphs incorporates the font's matrix already cgMatrix = CGAffineTransformConcat(cgMatrix, transform); if (matrix.isScaling()) @@ -785,7 +789,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition qreal pos_x = -br.x.truncate() + subPixelPosition.toReal(); qreal pos_y = im.height() + br.y.toReal(); - if (!isColorGlyph) { + if (!hasColorGlyphs()) { CGContextSetTextMatrix(ctx, cgMatrix); #if defined(Q_OS_MACOS) CGContextSetFillColorWithColor(ctx, glyphColor); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 2ce46a4706..13505be0aa 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -139,6 +139,7 @@ protected: void init(); QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; + bool hasColorGlyphs() const; QCFType ctfont; QCFType cgFont; -- cgit v1.2.3 From ae1f749e9e25495e4ae1658289584adb74d0b076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 21:51:21 +0100 Subject: CoreText: Rename argument to imageForGlyph to better reflect how it's used The 'aa' argument doesn't unconditionally enabled antialiasing, it just overrides the check that the pointSize is larger than the antialiasing threshold. If the styleStrategy has QFont::NoAntialias we still end up without antialiasing. Change-Id: I7130e7c68d883c2443756242e96790264f583b0f Reviewed-by: Simon Hausmann Reviewed-by: Allan Sandfeld Jensen --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 91d3d811b5..b323496038 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -732,7 +732,8 @@ bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias)); } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix) +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, + bool overrideAntialiasingThreshold, const QTransform &matrix) { glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); @@ -769,7 +770,8 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); CGContextSetFontSize(ctx, fontDef.pixelSize); - const bool antialias = (aa || fontDef.pointSize > antialiasingThreshold()) && !(fontDef.styleStrategy & QFont::NoAntialias); + const bool antialias = (overrideAntialiasingThreshold || fontDef.pointSize > antialiasingThreshold()) + && !(fontDef.styleStrategy & QFont::NoAntialias); CGContextSetShouldAntialias(ctx, antialias); const bool smoothing = antialias && !(fontDef.styleStrategy & QFont::NoSubpixelAntialias); CGContextSetShouldSmoothFonts(ctx, smoothing); -- cgit v1.2.3 From 3944f45c4d74b0389dc2246d1292790a9591ab82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 27 Nov 2018 17:13:38 +0100 Subject: CoreText: Remove handling of the AppleAntiAliasingThreshold user default The setting is not relevant for modern macOS applications, and none of the applications shipped with macOS today are affected by it. The only code path in macOS that picks it up is +[NSFont initialize] in the UIFoundation framework, storing it for later so that -[NSFont screenFont] and -[NSFont screenFontWithRenderingMode:] can use it, but these APIs are deprecated and we don't use them in Qt. Other NSFont code paths will not hit these APIs unless screen font substitution is enabled, something it hasn't been since OSX 10.7. https://preview.tinyurl.com/yctpfnqp Removing handling of this setting allows us to simplify the reasoning for whether or not antialiasing and font smoothing is enabled for a given engine. Change-Id: Ie2809052a1a0815d9bddedd4a6236eb6c898f993 Reviewed-by: Lars Knoll Reviewed-by: Allan Sandfeld Jensen --- .../fontdatabases/mac/qfontengine_coretext.mm | 26 +++++----------------- .../fontdatabases/mac/qfontengine_coretext_p.h | 3 +-- 2 files changed, 6 insertions(+), 23 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index b323496038..7a26416868 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -614,20 +614,6 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s return br; } -int QCoreTextFontEngine::antialiasingThreshold() -{ - static const int antialiasingThreshold = [] { - auto defaults = [NSUserDefaults standardUserDefaults]; - int threshold = [defaults integerForKey:@"AppleAntiAliasingThreshold"]; - qCDebug(lcQpaFonts) << "Resolved antialiasing threshold. Defaults =" - << [[defaults dictionaryRepresentation] dictionaryWithValuesForKeys:@[ - @"AppleAntiAliasingThreshold" - ]] << "Result =" << threshold; - return threshold; - }(); - return antialiasingThreshold; -} - /* Apple has gone through many iterations of its font smoothing algorithms, and there are many ways to enable or disable certain aspects of it. As @@ -732,8 +718,7 @@ bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias)); } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, - bool overrideAntialiasingThreshold, const QTransform &matrix) +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix) { glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); @@ -770,8 +755,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); CGContextSetFontSize(ctx, fontDef.pixelSize); - const bool antialias = (overrideAntialiasingThreshold || fontDef.pointSize > antialiasingThreshold()) - && !(fontDef.styleStrategy & QFont::NoAntialias); + const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); CGContextSetShouldAntialias(ctx, antialias); const bool smoothing = antialias && !(fontDef.styleStrategy & QFont::NoSubpixelAntialias); CGContextSetShouldSmoothFonts(ctx, smoothing); @@ -837,7 +821,7 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosit if (x.type() > QTransform::TxScale) return QFontEngine::alphaMapForGlyph(glyph, subPixelPosition, x); - QImage im = imageForGlyph(glyph, subPixelPosition, false, x); + QImage im = imageForGlyph(glyph, subPixelPosition, x); QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); @@ -859,7 +843,7 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo if (x.type() > QTransform::TxScale) return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, x); - QImage im = imageForGlyph(glyph, subPixelPosition, true, x); + QImage im = imageForGlyph(glyph, subPixelPosition, x); qGamma_correct_back_to_linear_cs(&im); return im; } @@ -869,7 +853,7 @@ QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPositio if (t.type() > QTransform::TxScale) return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t); - return imageForGlyph(glyph, subPixelPosition, true, t); + return imageForGlyph(glyph, subPixelPosition, t); } void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 13505be0aa..0ff428084f 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -127,7 +127,6 @@ public: Q_ENUM(FontSmoothing); static FontSmoothing fontSmoothing(); - static int antialiasingThreshold(); static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length); static QFont::Weight qtWeightFromCFWeight(float value); @@ -137,7 +136,7 @@ public: protected: QCoreTextFontEngine(const QFontDef &def); void init(); - QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); + QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; bool hasColorGlyphs() const; -- cgit v1.2.3 From ec254d2555083ff258db9675fa43ad23888f0685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 27 Nov 2018 18:52:29 +0100 Subject: CoreText: Add font antialiasing and smoothing helper functions The font smoothing helper in particular now takes into account whether or not we're dealing with color glyphs, in which case we shouldn't (or don't need to) smooth, and also makes sure the QFont::NoSubpixelAntialias style strategy doesn't affect font smoothing when we're dealing with non-subpixel-antialiased font smoothing, as on macOS 10.14. Change-Id: Ibd477158629402c55cafec31576b6d9901d184cf Reviewed-by: Lars Knoll Reviewed-by: Allan Sandfeld Jensen --- .../fontdatabases/mac/qfontengine_coretext.mm | 29 +++++++++++++++++++--- .../fontdatabases/mac/qfontengine_coretext_p.h | 2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7a26416868..6c2ffba92e 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -712,6 +712,28 @@ QCoreTextFontEngine::FontSmoothing QCoreTextFontEngine::fontSmoothing() return cachedFontSmoothing; } +bool QCoreTextFontEngine::shouldAntialias() const +{ + return !(fontDef.styleStrategy & QFont::NoAntialias); +} + +bool QCoreTextFontEngine::shouldSmoothFont() const +{ + if (hasColorGlyphs()) + return false; + + if (!shouldAntialias()) + return false; + + switch (fontSmoothing()) { + case Disabled: return false; + case Subpixel: return !(fontDef.styleStrategy & QFont::NoSubpixelAntialias); + case Grayscale: return true; + } + + Q_UNREACHABLE(); +} + bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const { // Only works well when font-smoothing is enabled @@ -755,10 +777,9 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); CGContextSetFontSize(ctx, fontDef.pixelSize); - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - CGContextSetShouldAntialias(ctx, antialias); - const bool smoothing = antialias && !(fontDef.styleStrategy & QFont::NoSubpixelAntialias); - CGContextSetShouldSmoothFonts(ctx, smoothing); + + CGContextSetShouldAntialias(ctx, shouldAntialias()); + CGContextSetShouldSmoothFonts(ctx, shouldSmoothFont()); CGAffineTransform cgMatrix = CGAffineTransformIdentity; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 0ff428084f..28810f13bc 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -139,6 +139,8 @@ protected: QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; bool hasColorGlyphs() const; + bool shouldAntialias() const; + bool shouldSmoothFont() const; QCFType ctfont; QCFType cgFont; -- cgit v1.2.3 From 0cf5648ce6df8b60090a14f738dd5d66643a0532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 28 Nov 2018 12:12:07 +0100 Subject: CoreText: Store glyphs in linear RGB when needed by blending algorithm Instead of tying the linear-conversion to a specific function, we move it to imageForGlyph and base it on the premise for needing it. Change-Id: Ib8fc79ad419ef703abcb82785ac15d4c75fb98e6 Reviewed-by: Lars Knoll Reviewed-by: Allan Sandfeld Jensen --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 6c2ffba92e..271f07e0c1 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -824,6 +824,9 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); } + if (expectsGammaCorrectedBlending()) + qGamma_correct_back_to_linear_cs(&im); + #if defined(Q_OS_MACOS) if (blackOnWhiteGlyphs) im.invertPixels(); @@ -864,9 +867,7 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo if (x.type() > QTransform::TxScale) return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, x); - QImage im = imageForGlyph(glyph, subPixelPosition, x); - qGamma_correct_back_to_linear_cs(&im); - return im; + return imageForGlyph(glyph, subPixelPosition, x); } QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) -- cgit v1.2.3 From 1f1dc3fc4c2e5e2d94e86dfc7235a4b762da2e72 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 16 Nov 2018 16:01:30 +0100 Subject: Fix gamma-correction in QCoreTextFontEngine with Mojave The code was previously assuming font-smoothing was only used with A32 font antialiasing, so the corresponding gamma-correction was not performed. Task-number: QTBUG-71075 Task-number: QTBUG-71946 Change-Id: I68d8304cf18638239d8bfac32c67333f16ccc7bd Reviewed-by: Lars Knoll --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 271f07e0c1..7fb22c0675 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -736,8 +736,7 @@ bool QCoreTextFontEngine::shouldSmoothFont() const bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const { - // Only works well when font-smoothing is enabled - return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias)); + return shouldSmoothFont(); } QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix) -- cgit v1.2.3 From c3a963da1f9e7b1d37e63eedded61da4fbdaaf9a Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 16 Nov 2018 17:07:33 +0100 Subject: src/3rdparty: remove xkbcommon The only reason why we bundled this library ~6 years ago was because it was not available on distributions that we supported at the time, but library was a hard dependency for XCB plugin. See: 2122e731abdb619249df89642c0800640b2fa428 Later more and more projects started to depend on it (compose input context plugin, libinput, mir, wayland). The configuration had become too complex, because some projects used bundled and some used the version from the system. Having libxkbcommon in 3rdparty sources is not necessary anymore, after RHEL 6.6 was removed from the list of supported platforms for Qt 5.12. Ubuntu 16.04 - 0.5.0 Ubuntu 18.04 - 0.8.0 openSUSE 42.3 - 0.6.1 RHEL-7.4 - 0.7.1 This will also simplify further development, e.g. QTBUG-42181 Bumped the minimal required version 0.4.1 -> 0.5.0. The patch also contains a code marked with "TRANSITION HACK", which is temporary needed so we can update the dependent wayland module. [ChangeLog][Third-Party Code] Removed xkbcommon from bundled sources. This library is present on all supported platforms. The minimal required version now is 0.5.0. Task-number: QTBUG-65503 Change-Id: Iec50829bb6f8fbb19f3c4e4ad62e332beb837de5 Reviewed-by: Lars Knoll Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- src/platformsupport/input/libinput/libinput.pri | 5 +---- src/platformsupport/input/libinput/qlibinputkeyboard.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/input/libinput/libinput.pri b/src/platformsupport/input/libinput/libinput.pri index f922769a37..476f20c1b8 100644 --- a/src/platformsupport/input/libinput/libinput.pri +++ b/src/platformsupport/input/libinput/libinput.pri @@ -14,7 +14,4 @@ QMAKE_USE_PRIVATE += libudev libinput INCLUDEPATH += $$PWD/../shared -qtConfig(xkbcommon-evdev): \ - QMAKE_USE_PRIVATE += xkbcommon_evdev -else: \ - DEFINES += QT_NO_XKBCOMMON_EVDEV +qtConfig(xkbcommon): QMAKE_USE_PRIVATE += xkbcommon diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index 2524066301..baef769bc9 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -44,7 +44,7 @@ #include #include #include -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) #include #include #endif @@ -56,7 +56,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcLibInput) const int REPEAT_DELAY = 500; const int REPEAT_RATE = 100; -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) struct KeyTabEntry { int xkbkey; int qtkey; @@ -132,14 +132,14 @@ static const KeyTabEntry keyTab[] = { #endif QLibInputKeyboard::QLibInputKeyboard() -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) : m_ctx(0), m_keymap(0), m_state(0), m_mods(Qt::NoModifier) #endif { -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) qCDebug(qLcLibInput) << "Using xkbcommon for key mapping"; m_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!m_ctx) { @@ -164,13 +164,13 @@ QLibInputKeyboard::QLibInputKeyboard() m_repeatTimer.setSingleShot(true); connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat); #else - qCWarning(qLcLibInput) << "X-less xkbcommon not available, not performing key mapping"; + qCWarning(qLcLibInput) << "xkbcommon not available, not performing key mapping"; #endif } QLibInputKeyboard::~QLibInputKeyboard() { -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) if (m_state) xkb_state_unref(m_state); if (m_keymap) @@ -182,7 +182,7 @@ QLibInputKeyboard::~QLibInputKeyboard() void QLibInputKeyboard::processKey(libinput_event_keyboard *e) { -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) if (!m_ctx || !m_keymap || !m_state) return; @@ -245,7 +245,7 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) #endif } -#ifndef QT_NO_XKBCOMMON_EVDEV +#if QT_CONFIG(xkbcommon) void QLibInputKeyboard::handleRepeat() { QWindowSystemInterface::handleExtendedKeyEvent(nullptr, QEvent::KeyPress, -- cgit v1.2.3 From b926d5f919d2564cfdece497a87111a02e927db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 26 Nov 2018 23:01:50 +0100 Subject: CoreText: Remove handling of QFontEngineMulti's highByte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a leftover from when the Cocoa plugin used QFontEngineMulti exclusively. Nowadays QFontEngineMulti will strip out the highByte before calling into the real engine. Left an assert just in case.. Change-Id: I6cb26d20a908d7c3aaf096297fca160805fdb85b Reviewed-by: Simon Hausmann Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- .../fontdatabases/mac/qfontengine_coretext.mm | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7fb22c0675..0f8727a13c 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -885,10 +885,8 @@ void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shap QVarLengthArray cgGlyphs(numGlyphs); for (int i = 0; i < numGlyphs; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - cgGlyphs[i] = 0; - else - cgGlyphs[i] = glyphs->glyphs[i]; + Q_ASSERT(!QFontEngineMulti::highByte(glyphs->glyphs[i])); + cgGlyphs[i] = glyphs->glyphs[i]; } loadAdvancesForGlyphs(cgGlyphs, glyphs); @@ -901,14 +899,9 @@ void QCoreTextFontEngine::loadAdvancesForGlyphs(QVarLengthArray &cgGlyp CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), numGlyphs); for (int i = 0; i < numGlyphs; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - continue; - glyphs->advances[i] = QFixed::fromReal(advances[i].width); - } - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < numGlyphs; ++i) - glyphs->advances[i] = glyphs->advances[i].round(); + QFixed advance = QFixed::fromReal(advances[i].width); + glyphs->advances[i] = fontDef.styleStrategy & QFont::ForceIntegerMetrics + ? advance.round() : advance; } } -- cgit v1.2.3 From 64037f18d308c936848b7db2324bdb5dadb85a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 30 Nov 2018 12:03:58 +0100 Subject: CoreText: Respect QFont::NoSubpixelAntialias when deciding glyph format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I846758bce2fd7536f9941b11f23fc0e5d5bc6f1b Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 0f8727a13c..a1299154cb 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -235,7 +235,7 @@ void QCoreTextFontEngine::init() if (traits & kCTFontColorGlyphsTrait) glyphFormat = QFontEngine::Format_ARGB; - else if (fontSmoothing() == FontSmoothing::Subpixel) + else if (shouldSmoothFont() && fontSmoothing() == FontSmoothing::Subpixel) glyphFormat = QFontEngine::Format_A32; else glyphFormat = QFontEngine::Format_A8; -- cgit v1.2.3 From e11a3b3f3e41050e048a586a8de2bd68c5ed3cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 28 Nov 2018 12:17:58 +0100 Subject: CoreText: Base glyph fill color logic on font smoothing algorithm Change-Id: I22be1efb1f91048745008ea1b49186b39367d122 Reviewed-by: Lars Knoll --- .../fontdatabases/mac/qfontengine_coretext.mm | 57 ++++++++++++---------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index a1299154cb..3dd3f468f2 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -748,37 +748,44 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition if (!im.width() || !im.height()) return im; -#if defined(Q_OS_MACOS) - CGColorRef glyphColor = CGColorGetConstantColor(kCGColorWhite); - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) { - // macOS 10.14 uses a new font smoothing algorithm that takes the fill color into - // account. This means our default approach of drawing white on black to produce - // the alpha map will result in non-native looking text when then drawn as black - // on white during the final blit. As a workaround we use the application's current - // appearance to decide whether to draw with white or black fill, and then invert - // the glyph image in the latter case, producing an alpha map. This covers the - // most common use-cases, but longer term we should propagate the fill color all - // the way from the paint engine, and include it in the key for the glyph cache. - if (!qt_mac_applicationIsInDarkMode()) - glyphColor = CGColorGetConstantColor(kCGColorBlack); - } - const bool blackOnWhiteGlyphs = !hasColorGlyphs() - && CGColorEqualToColor(glyphColor, CGColorGetConstantColor(kCGColorBlack)); - if (blackOnWhiteGlyphs) - im.fill(Qt::white); - else -#endif - im.fill(0); // Faster than Qt::black - QCFType colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); QCFType ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, qt_mac_bitmapInfoForImage(im)); Q_ASSERT(ctx); - CGContextSetFontSize(ctx, fontDef.pixelSize); CGContextSetShouldAntialias(ctx, shouldAntialias()); - CGContextSetShouldSmoothFonts(ctx, shouldSmoothFont()); + + const bool shouldSmooth = shouldSmoothFont(); + CGContextSetShouldSmoothFonts(ctx, shouldSmooth); + +#if defined(Q_OS_MACOS) + auto glyphColor = [&] { + if (shouldSmooth && fontSmoothing() == Grayscale) { + // The grayscale font smoothing algorithm introduced in macOS Mojave (10.14) adjusts + // its dilation (stem darkening) parameters based on the fill color. This means our + // default approach of drawing white on black to produce the alpha map will result + // in non-native looking text when then drawn as black on white during the final blit. + // As a workaround we use the application's current appearance to decide whether to + // draw with white or black fill, and then invert the glyph image in the latter case, + // producing an alpha map. This covers the most common use-cases, but longer term we + // should propagate the fill color all the way from the paint engine, and include it + //in the key for the glyph cache. + + if (!qt_mac_applicationIsInDarkMode()) + return kCGColorBlack; + } + return kCGColorWhite; + }(); + + const bool blackOnWhiteGlyphs = glyphColor == kCGColorBlack; + if (blackOnWhiteGlyphs) + im.fill(Qt::white); + else +#endif + im.fill(0); + + CGContextSetFontSize(ctx, fontDef.pixelSize); CGAffineTransform cgMatrix = CGAffineTransformIdentity; @@ -798,7 +805,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition if (!hasColorGlyphs()) { CGContextSetTextMatrix(ctx, cgMatrix); #if defined(Q_OS_MACOS) - CGContextSetFillColorWithColor(ctx, glyphColor); + CGContextSetFillColorWithColor(ctx, CGColorGetConstantColor(glyphColor)); #else CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); #endif -- cgit v1.2.3 From 58e66a2573e40cc3e12a5479575a8ecbef1be6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 27 Nov 2018 19:13:54 +0100 Subject: CoreText: Define font smoothing gamma along with rest of relevant code Change-Id: I57909603732de6c1a91c744a358968941e64acdf Reviewed-by: Lars Knoll --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 5 +++++ src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h | 1 + 2 files changed, 6 insertions(+) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 3dd3f468f2..19b450b643 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -739,6 +739,11 @@ bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const return shouldSmoothFont(); } +qreal QCoreTextFontEngine::fontSmoothingGamma() +{ + return 2.0; +} + QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix) { glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 28810f13bc..4064507058 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -127,6 +127,7 @@ public: Q_ENUM(FontSmoothing); static FontSmoothing fontSmoothing(); + static qreal fontSmoothingGamma(); static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length); static QFont::Weight qtWeightFromCFWeight(float value); -- cgit v1.2.3 From 17ced070fd1e55948659bc37c421f98074910599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 9 Nov 2018 17:56:08 +0100 Subject: Read font selection flags and use them when querying for metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Certain fonts with multiple styles have the same family name. When loading these as application fonts we were not specific enough when querying for the text metrics. This meant that e.g. the bold version in a font family would get the metrics of the regular one. Fixes: QTBUG-67273 Change-Id: Ic988d62cddde0a1f77ddcaf2891cadc21c9b31e6 Reviewed-by: Mårten Nordheim Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../fontdatabases/windows/qwindowsfontdatabase.cpp | 39 ++++++++++++++++++---- .../fontdatabases/windows/qwindowsfontdatabase_p.h | 8 +++++ 2 files changed, 41 insertions(+), 6 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index c70d507b99..9ff50bdf05 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -1490,7 +1490,8 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, static void getFamiliesAndSignatures(const QByteArray &fontData, QList *families, - QVector *signatures) + QVector *signatures, + QVector *values) { const uchar *data = reinterpret_cast(fontData.constData()); @@ -1511,9 +1512,25 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, families->append(qMove(names)); + if (values || signatures) + getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); + + if (values) { + QFontValues fontValues; + if (table && length >= 64) { + // Read in some details about the font, offset calculated based on the specification + fontValues.weight = qFromBigEndian(table + 4); + + quint16 fsSelection = qFromBigEndian(table + 62); + fontValues.isItalic = (fsSelection & 1) != 0; + fontValues.isUnderlined = (fsSelection & (1 << 1)) != 0; + fontValues.isOverstruck = (fsSelection & (1 << 4)) != 0; + } + values->append(std::move(fontValues)); + } + if (signatures) { FONTSIGNATURE signature; - getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); if (table && length >= 86) { // Offsets taken from OS/2 table in the TrueType spec signature.fsUsb[0] = qFromBigEndian(table + 42); @@ -1536,11 +1553,12 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, WinApplicationFont font; font.fileName = fileName; QVector signatures; + QVector fontValues; QList families; QStringList familyNames; if (!fontData.isEmpty()) { - getFamiliesAndSignatures(fontData, &families, &signatures); + getFamiliesAndSignatures(fontData, &families, &signatures, &fontValues); if (families.isEmpty()) return familyNames; @@ -1553,14 +1571,23 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, // Memory fonts won't show up in enumeration, so do add them the hard way. for (int j = 0; j < families.count(); ++j) { - const QString familyName = families.at(j).name; - const QString styleName = families.at(j).style; + const auto &family = families.at(j); + const QString &familyName = family.name; + const QString &styleName = family.style; familyNames << familyName; HDC hdc = GetDC(0); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size())); lf.lfCharSet = DEFAULT_CHARSET; + const QFontValues &values = fontValues.at(j); + lf.lfWeight = values.weight; + if (values.isItalic) + lf.lfItalic = TRUE; + if (values.isOverstruck) + lf.lfStrikeOut = TRUE; + if (values.isUnderlined) + lf.lfUnderline = TRUE; HFONT hfont = CreateFontIndirect(&lf); HGDIOBJ oldobj = SelectObject(hdc, hfont); @@ -1581,7 +1608,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, QByteArray data = f.readAll(); f.close(); - getFamiliesAndSignatures(data, &families, 0); + getFamiliesAndSignatures(data, &families, nullptr, nullptr); if (families.isEmpty()) return QStringList(); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index ab6d6307c7..9d0aa7f723 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -177,6 +177,14 @@ struct QFontNames QString preferredStyle; // e.g. "Condensed Italic" }; +struct QFontValues +{ + quint16 weight = 0; + bool isItalic = false; + bool isOverstruck = false; + bool isUnderlined = false; +}; + bool qt_localizedName(const QString &name); QString qt_getEnglishName(const QString &familyName, bool includeStyle = false); QFontNames qt_getCanonicalFontNames(const LOGFONT &lf); -- cgit v1.2.3