[Cocoa] System fonts do not get correct tracking
[WebKit-https.git] / Source / WebCore / platform / graphics / cocoa / FontCocoa.mm
index b22735ccbb1016b5410f6ebc7cb488cdbf7b5999..2c266d08059eb2ae6015f32129c20c0c2175d569 100644 (file)
@@ -267,15 +267,16 @@ void Font::platformInit()
     if (platformData().orientation() == Vertical && !isTextOrientationFallback())
         m_hasVerticalGlyphs = fontHasVerticalGlyphs(m_platformData.ctFont());
 
-    if (!m_platformData.m_isEmoji)
-        return;
-
-    int thirdOfSize = m_platformData.size() / 3;
-    m_fontMetrics.setAscent(thirdOfSize);
-    m_fontMetrics.setDescent(thirdOfSize);
-    m_fontMetrics.setLineGap(thirdOfSize);
-    m_fontMetrics.setLineSpacing(0);
+    if (m_platformData.m_isEmoji) {
+        int thirdOfSize = m_platformData.size() / 3;
+        m_fontMetrics.setAscent(thirdOfSize);
+        m_fontMetrics.setDescent(thirdOfSize);
+        m_fontMetrics.setLineGap(thirdOfSize);
+        m_fontMetrics.setLineSpacing(0);
+    }
 #endif
+
+    m_isSystemFont = CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(m_platformData.font())).get());
 }
 
 void Font::platformCharWidthInit()
@@ -339,7 +340,7 @@ PassRefPtr<Font> Font::platformCreateScaledFont(const FontDescription&, float sc
         scaledFontData.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(scaledFontTraits & NSBoldFontMask);
         scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask);
 
-        return FontCache::singleton().fontForPlatformData(scaledFontData);
+        return Font::create(scaledFontData);
     }
     END_BLOCK_OBJC_EXCEPTIONS;
 
@@ -360,7 +361,7 @@ PassRefPtr<Font> Font::platformCreateScaledFont(const FontDescription&, float sc
         scaledFontData.m_syntheticBold = (fontTraits & kCTFontBoldTrait) && !(scaledFontTraits & kCTFontTraitBold);
         scaledFontData.m_syntheticOblique = (fontTraits & kCTFontItalicTrait) && !(scaledFontTraits & kCTFontTraitItalic);
 
-        return FontCache::singleton().fontForPlatformData(scaledFontData);
+        return Font::create(scaledFontData);
     }
 
     return nullptr;
@@ -405,7 +406,7 @@ void Font::determinePitch()
 FloatRect Font::platformBoundsForGlyph(Glyph glyph) const
 {
     FloatRect boundingBox;
-    boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
+    boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontOrientationVertical : kCTFontOrientationHorizontal, &glyph, 0, 1);
     boundingBox.setY(-boundingBox.maxY());
     if (m_syntheticBoldOffset)
         boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
@@ -454,9 +455,9 @@ static inline bool advanceForColorBitmapFont(const FontPlatformData& platformDat
 #endif
 }
 
-static bool hasCustomTracking(CTFontRef font)
+static inline bool hasCustomTracking(const Font& font)
 {
-    return CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(font)).get());
+    return font.isSystemFont();
 }
 
 static inline bool isEmoji(const FontPlatformData& platformData)
@@ -469,10 +470,11 @@ static inline bool isEmoji(const FontPlatformData& platformData)
 #endif
 }
 
-static inline bool canUseFastGlyphAdvanceGetter(const FontPlatformData& platformData, Glyph glyph, CGSize& advance, bool& populatedAdvance)
+static inline bool canUseFastGlyphAdvanceGetter(const Font& font, Glyph glyph, CGSize& advance, bool& populatedAdvance)
 {
+    const FontPlatformData& platformData = font.platformData();
     // Fast getter doesn't take custom tracking into account
-    if (hasCustomTracking(platformData.ctFont()))
+    if (hasCustomTracking(font))
         return false;
     // Fast getter doesn't work for emoji
     if (isEmoji(platformData))
@@ -490,7 +492,7 @@ float Font::platformWidthForGlyph(Glyph glyph) const
     CGSize advance = CGSizeZero;
     bool horizontal = platformData().orientation() == Horizontal;
     bool populatedAdvance = false;
-    if ((horizontal || m_isBrokenIdeographFallback) && canUseFastGlyphAdvanceGetter(platformData(), glyph, advance, populatedAdvance)) {
+    if ((horizontal || m_isBrokenIdeographFallback) && canUseFastGlyphAdvanceGetter(*this, glyph, advance, populatedAdvance)) {
         float pointSize = platformData().m_size;
         CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
         if (!CGFontGetGlyphAdvancesForStyle(platformData().cgFont(), &m, renderingStyle(platformData()), &glyph, 1, &advance)) {
@@ -498,8 +500,15 @@ float Font::platformWidthForGlyph(Glyph glyph) const
             LOG_ERROR("Unable to cache glyph widths for %@ %f", fullName.get(), pointSize);
             advance.width = 0;
         }
-    } else if (!populatedAdvance)
-        CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), horizontal ? kCTFontHorizontalOrientation : kCTFontVerticalOrientation, &glyph, &advance, 1);
+    } else if (!populatedAdvance) {
+        // m_platformData.font() returns the original font that was passed into the FontPlatformData constructor.\10 In the case of fonts that have custom tracking,
+        // the custom tracking does not survive the transformation to either m_platformData.cgFont() nor m_platformData.ctFont(), so we must use the original
+        // font() that was passed in. However, for web fonts, m_platformData.font() is null, so we must use m_platformData.ctFont() for those cases.
+        if (hasCustomTracking(*this))
+            CTFontGetAdvancesForGlyphs(m_platformData.font(), horizontal ? kCTFontOrientationHorizontal : kCTFontOrientationVertical, &glyph, &advance, 1);
+        else
+            CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), horizontal ? kCTFontOrientationHorizontal : kCTFontOrientationVertical, &glyph, &advance, 1);
+    }
 
     return advance.width + m_syntheticBoldOffset;
 }