CoreText: Base glyph fill color logic on font smoothing algorithm

Change-Id: I22be1efb1f91048745008ea1b49186b39367d122
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Tor Arne Vestbø 2018-11-28 12:17:58 +01:00
parent 10f9bd82ea
commit e11a3b3f3e
1 changed files with 32 additions and 25 deletions

View File

@ -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<CGColorSpaceRef> colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
QCFType<CGContextRef> 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