From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 22 Oct 2018 10:45:53 -0700
Subject: fix_font_thickness.patch

Backports https://skia-review.googlesource.com/c/157566/ to
fix an issue whereby font rendering weight was too thin compared
to other fonts present on MacOS Mojave.

diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 18d09b4ec06a23f8c046d4f08a51296b77e37d8b..fc3902156b65b5875d231ff52101764d7b068f91 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -380,17 +380,28 @@ static constexpr const uint8_t kSpiderSymbol_ttf[] = {
     0x00, 0x02, 0x00, 0x00
 };
 
+enum class SmoothBehavior {
+    none, // SmoothFonts produces no effect.
+    some, // SmoothFonts produces some effect, but not subpixel coverage.
+    subpixel, // SmoothFonts produces some effect and provides subpixel coverage.
+};
+
 /**
  * There does not appear to be a publicly accessable API for determining if lcd
  * font smoothing will be applied if we request it. The main issue is that if
  * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
  */
-static bool supports_LCD() {
-    static bool gSupportsLCD = []{
-        uint32_t bitmap[16][16] = {};
+static SmoothBehavior smooth_behavior() {
+    static SmoothBehavior gSmoothBehavior = []{
+        uint32_t noSmoothBitmap[16][16] = {};
+        uint32_t smoothBitmap[16][16] = {};
         UniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
-        UniqueCFRef<CGContextRef> cgContext(
-                CGBitmapContextCreate(&bitmap, 16, 16, 8, 16*4, colorspace.get(), BITMAP_INFO_RGB));
+        UniqueCFRef<CGContextRef> noSmoothContext(
+                CGBitmapContextCreate(&noSmoothBitmap, 16, 16, 8, 16*4,
+                                      colorspace.get(), BITMAP_INFO_RGB));
+        UniqueCFRef<CGContextRef> smoothContext(
+                CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
+                                      colorspace.get(), BITMAP_INFO_RGB));
 
         UniqueCFRef<CGDataProviderRef> data(
                 CGDataProviderCreateWithData(nullptr, kSpiderSymbol_ttf,
@@ -401,31 +412,39 @@ static bool supports_LCD() {
                 CTFontCreateWithGraphicsFont(cgFont.get(), 16, nullptr, nullptr));
         SkASSERT(ctFont);
 
-        CGContextSetShouldSmoothFonts(cgContext.get(), true);
-        CGContextSetShouldAntialias(cgContext.get(), true);
-        CGContextSetTextDrawingMode(cgContext.get(), kCGTextFill);
-        CGContextSetGrayFillColor(cgContext.get(), 1, 1);
+        CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
+        CGContextSetShouldAntialias(noSmoothContext.get(), true);
+        CGContextSetTextDrawingMode(noSmoothContext.get(), kCGTextFill);
+        CGContextSetGrayFillColor(noSmoothContext.get(), 1, 1);
+
+        CGContextSetShouldSmoothFonts(smoothContext.get(), true);
+        CGContextSetShouldAntialias(smoothContext.get(), true);
+        CGContextSetTextDrawingMode(smoothContext.get(), kCGTextFill);
+        CGContextSetGrayFillColor(smoothContext.get(), 1, 1);
         CGPoint point = CGPointMake(0, 3);
         CGGlyph spiderGlyph = 3;
-        CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, cgContext.get());
+        CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, noSmoothContext.get());
+        CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, smoothContext.get());
 
         // For debugging.
-        //UniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(cgContext.get()));
+        //UniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(noSmoothContext()));
+        //UniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(smoothContext()));
 
+        SmoothBehavior smoothBehavior = SmoothBehavior::none;
         for (int x = 0; x < 16; ++x) {
             for (int y = 0; y < 16; ++y) {
-                uint32_t pixel = bitmap[x][y];
-                uint32_t r = (pixel >> 16) & 0xFF;
-                uint32_t g = (pixel >>  8) & 0xFF;
-                uint32_t b = (pixel >>  0) & 0xFF;
+                uint32_t smoothPixel = smoothBitmap[x][y];
+                uint32_t r = (smoothPixel >> 16) & 0xFF;
+                uint32_t g = (smoothPixel >>  8) & 0xFF;
+                uint32_t b = (smoothPixel >>  0) & 0xFF;
                 if (r != g || r != b) {
-                    return true;
+                    return SmoothBehavior::subpixel;
                 }
             }
         }
-        return false;
+        return smoothBehavior;
     }();
-    return gSupportsLCD;
+    return gSmoothBehavior;
 }
 
 class Offscreen {
@@ -1008,7 +1027,7 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
     if (!fRGBSpace) {
         //It doesn't appear to matter what color space is specified.
         //Regular blends and antialiased text are always (s*a + d*(1-a))
-        //and smoothed text is always g=2.0.
+        //and subpixel antialiased text is always g=2.0.
         fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
     }
 
@@ -1264,7 +1283,7 @@ static constexpr uint8_t sk_pow2_table(size_t i) {
  *  This will invert the gamma applied by CoreGraphics, so we can get linear
  *  values.
  *
- *  CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
+ *  CoreGraphics obscurely defaults to 2.0 as the subpixel coverage gamma value.
  *  The color space used does not appear to affect this choice.
  */
 static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
@@ -1354,18 +1373,20 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
     CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
 
     // FIXME: lcd smoothed un-hinted rasterization unsupported.
-    bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting;
+    bool requestSmooth = fRec.getHinting() != SkPaint::kNo_Hinting;
 
     // Draw the glyph
     size_t cgRowBytes;
-    CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD);
+    CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, requestSmooth);
     if (cgPixels == nullptr) {
         return;
     }
 
     // Fix the glyph
     if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
-        (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD))
+        (glyph.fMaskFormat == SkMask::kA8_Format
+         && requestSmooth
+         && smooth_behavior() == SmoothBehavior::subpixel))
     {
         const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
 
@@ -2261,14 +2282,14 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
 
     rec->fFlags &= ~flagsWeDontSupport;
 
-    bool lcdSupport = supports_LCD();
+    SmoothBehavior smoothBehavior = smooth_behavior();
 
     // Only two levels of hinting are supported.
     // kNo_Hinting means avoid CoreGraphics outline dilation.
     // kNormal_Hinting means CoreGraphics outline dilation is allowed.
     // If there is no lcd support, hinting (dilation) cannot be supported.
     SkPaint::Hinting hinting = rec->getHinting();
-    if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) {
+    if (SkPaint::kSlight_Hinting == hinting || smoothBehavior == SmoothBehavior::none) {
         hinting = SkPaint::kNo_Hinting;
     } else if (SkPaint::kFull_Hinting == hinting) {
         hinting = SkPaint::kNormal_Hinting;
@@ -2295,12 +2316,15 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
     // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
 
     if (rec->fMaskFormat == SkMask::kLCD16_Format) {
-        if (lcdSupport) {
+        if (smoothBehavior == SmoothBehavior::subpixel) {
             //CoreGraphics creates 555 masks for smoothed text anyway.
             rec->fMaskFormat = SkMask::kLCD16_Format;
             rec->setHinting(SkPaint::kNormal_Hinting);
         } else {
             rec->fMaskFormat = SkMask::kA8_Format;
+            if (smoothBehavior == SmoothBehavior::some) {
+                rec->setHinting(SkPaint::kNormal_Hinting);
+            }
         }
     }
 
