Add experimental code to use custom font dilation when rendering into non-opaque...
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2015 04:15:01 +0000 (04:15 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2015 04:15:01 +0000 (04:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143508

Reviewed by Sam Weinig.

Add GraphicsContext::setAntialiasedFontDilationEnabled(), and set it to true
when rendering into a compositing layer which is not opaque (at the same location
where we disable font smoothing).

If Settings::antialiasedFontDilationEnabled() is true, when rendering non-smoothed
text (and if CSS hasn't opted into antialiased mode), use custom font dilation
parameters, chosen using a light/medium/dark heuristic, to make this text
match more closely with LCD-smoothed text.

* page/Settings.cpp:
(WebCore::Settings::Settings):
(WebCore::Settings::setAntialiasedFontDilationEnabled): Set global state
in FontCascade (which can't easily get at Settings). This it not ideal,
but is temporary.
* page/Settings.h:
(WebCore::Settings::antialiasedFontDilationEnabled):
* page/Settings.in: Can't autogenerate this setting any more.
* platform/graphics/FontCascade.cpp:
(WebCore::FontCascade::setAntialiasedFontDilationEnabled): Set the global.
(WebCore::FontCascade::antialiasedFontDilationEnabled):
* platform/graphics/FontCascade.h:
* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::setAntialiasedFontDilationEnabled): Set graphics state
to say that we should do dilation of antialiased text.
* platform/graphics/GraphicsContext.h:
(WebCore::GraphicsContextState::GraphicsContextState):
(WebCore::GraphicsContext::antialiasedFontDilationEnabled):
* platform/graphics/ca/mac/PlatformCALayerMac.mm:
(PlatformCALayer::drawLayerContents): If the layer is not opaque, enable the
dilated text code path.
* platform/graphics/cocoa/FontCascadeCocoa.mm:
(WebCore::dilationSizeForTextColor): Heuristic (values chosen empirically) to
computed custom dilation based on foreground color.
(WebCore::FontCascade::drawGlyphs): Set the custom dilation parameters, and the
antialiasing state if we're not doing smoothing, and CSS hasn't opted into the
antialiased path.
* platform/spi/cg/CoreGraphicsSPI.h: New SPI.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@182516 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/page/Settings.cpp
Source/WebCore/page/Settings.h
Source/WebCore/page/Settings.in
Source/WebCore/platform/graphics/FontCascade.cpp
Source/WebCore/platform/graphics/FontCascade.h
Source/WebCore/platform/graphics/GraphicsContext.cpp
Source/WebCore/platform/graphics/GraphicsContext.h
Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm
Source/WebCore/platform/spi/cg/CoreGraphicsSPI.h

index 1a55243..e4a7d39 100644 (file)
@@ -1,3 +1,48 @@
+2015-04-07  Simon Fraser  <simon.fraser@apple.com>
+
+        Add experimental code to use custom font dilation when rendering into non-opaque contexts
+        https://bugs.webkit.org/show_bug.cgi?id=143508
+
+        Reviewed by Sam Weinig.
+
+        Add GraphicsContext::setAntialiasedFontDilationEnabled(), and set it to true
+        when rendering into a compositing layer which is not opaque (at the same location
+        where we disable font smoothing).
+
+        If Settings::antialiasedFontDilationEnabled() is true, when rendering non-smoothed
+        text (and if CSS hasn't opted into antialiased mode), use custom font dilation
+        parameters, chosen using a light/medium/dark heuristic, to make this text
+        match more closely with LCD-smoothed text.
+
+        * page/Settings.cpp:
+        (WebCore::Settings::Settings):
+        (WebCore::Settings::setAntialiasedFontDilationEnabled): Set global state
+        in FontCascade (which can't easily get at Settings). This it not ideal,
+        but is temporary.
+        * page/Settings.h:
+        (WebCore::Settings::antialiasedFontDilationEnabled):
+        * page/Settings.in: Can't autogenerate this setting any more.
+        * platform/graphics/FontCascade.cpp:
+        (WebCore::FontCascade::setAntialiasedFontDilationEnabled): Set the global.
+        (WebCore::FontCascade::antialiasedFontDilationEnabled):
+        * platform/graphics/FontCascade.h:
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::setAntialiasedFontDilationEnabled): Set graphics state
+        to say that we should do dilation of antialiased text.
+        * platform/graphics/GraphicsContext.h:
+        (WebCore::GraphicsContextState::GraphicsContextState):
+        (WebCore::GraphicsContext::antialiasedFontDilationEnabled):
+        * platform/graphics/ca/mac/PlatformCALayerMac.mm:
+        (PlatformCALayer::drawLayerContents): If the layer is not opaque, enable the
+        dilated text code path.
+        * platform/graphics/cocoa/FontCascadeCocoa.mm:
+        (WebCore::dilationSizeForTextColor): Heuristic (values chosen empirically) to
+        computed custom dilation based on foreground color.
+        (WebCore::FontCascade::drawGlyphs): Set the custom dilation parameters, and the
+        antialiasing state if we're not doing smoothing, and CSS hasn't opted into the
+        antialiased path.
+        * platform/spi/cg/CoreGraphicsSPI.h: New SPI.
+
 2015-04-07  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r182511.
index abbf835..0a5f3d4 100644 (file)
@@ -180,6 +180,7 @@ Settings::Settings(Page* page)
     , m_needsAdobeFrameReloadingQuirk(false)
     , m_usesPageCache(false)
     , m_fontRenderingMode(0)
+    , m_antialiasedFontDilationEnabled(true)
     , m_showTiledScrollingIndicator(false)
     , m_backgroundShouldExtendBeyondPage(false)
     , m_dnsPrefetchingEnabled(false)
@@ -341,6 +342,12 @@ void Settings::setTextAutosizingFontScaleFactor(float fontScaleFactor)
 
 #endif
 
+void Settings::setAntialiasedFontDilationEnabled(bool enabled)
+{
+    // FIXME: It's wrong for a setting to toggle a global, but this code is temporary.
+    FontCascade::setAntialiasedFontDilationEnabled(enabled);
+}
+
 void Settings::setMediaTypeOverride(const String& mediaTypeOverride)
 {
     if (m_mediaTypeOverride == mediaTypeOverride)
index 78620e3..4242205 100644 (file)
@@ -109,6 +109,9 @@ public:
     const IntSize& textAutosizingWindowSizeOverride() const { return m_textAutosizingWindowSizeOverride; }
 #endif
 
+    WEBCORE_EXPORT void setAntialiasedFontDilationEnabled(bool);
+    bool antialiasedFontDilationEnabled() const { return m_antialiasedFontDilationEnabled; }
+
     // Only set by Layout Tests.
     WEBCORE_EXPORT void setMediaTypeOverride(const String&);
     const String& mediaTypeOverride() const { return m_mediaTypeOverride; }
@@ -295,6 +298,7 @@ private:
     bool m_needsAdobeFrameReloadingQuirk : 1;
     bool m_usesPageCache : 1;
     unsigned m_fontRenderingMode : 1;
+    bool m_antialiasedFontDilationEnabled : 1;
     bool m_showTiledScrollingIndicator : 1;
     bool m_backgroundShouldExtendBeyondPage : 1;
     bool m_dnsPrefetchingEnabled : 1;
index 83c7b76..bb267dd 100644 (file)
@@ -36,7 +36,6 @@ minimumFontSize type=int, initial=0, setNeedsStyleRecalcInAllFrames=1
 minimumLogicalFontSize type=int, initial=0, setNeedsStyleRecalcInAllFrames=1
 defaultFontSize type=int, initial=0, setNeedsStyleRecalcInAllFrames=1
 defaultFixedFontSize type=int, initial=0, setNeedsStyleRecalcInAllFrames=1
-antialiasedFontDilationEnabled type=bool, initial=true, setNeedsStyleRecalcInAllFrames=1
 
 editingBehaviorType type=EditingBehaviorType, initial=editingBehaviorTypeForPlatform()
 maximumHTMLParserDOMTreeDepth type=unsigned, initial=defaultMaximumHTMLParserDOMTreeDepth
index 6806e6f..90ae625 100644 (file)
@@ -592,6 +592,18 @@ bool FontCascade::shouldUseSmoothing()
     return shouldUseFontSmoothing;
 }
 
+static bool antialiasedFontDilationIsEnabled = true;
+
+void FontCascade::setAntialiasedFontDilationEnabled(bool enabled)
+{
+    antialiasedFontDilationIsEnabled = enabled;
+}
+
+bool FontCascade::antialiasedFontDilationEnabled()
+{
+    return antialiasedFontDilationIsEnabled;
+}
+
 void FontCascade::setCodePath(CodePath p)
 {
     s_codePath = p;
index 66a34e8..75102fe 100644 (file)
@@ -205,6 +205,9 @@ public:
     static bool leadingExpansionOpportunity(const StringView&, TextDirection);
     static bool trailingExpansionOpportunity(const StringView&, TextDirection);
 
+    WEBCORE_EXPORT static void setAntialiasedFontDilationEnabled(bool);
+    WEBCORE_EXPORT static bool antialiasedFontDilationEnabled();
+
     WEBCORE_EXPORT static void setShouldUseSmoothing(bool);
     WEBCORE_EXPORT static bool shouldUseSmoothing();
 
index 3704066..1337878 100644 (file)
@@ -257,6 +257,11 @@ void GraphicsContext::setShouldSmoothFonts(bool shouldSmoothFonts)
     setPlatformShouldSmoothFonts(shouldSmoothFonts);
 }
 
+void GraphicsContext::setAntialiasedFontDilationEnabled(bool antialiasedFontDilationEnabled)
+{
+    m_state.antialiasedFontDilationEnabled = antialiasedFontDilationEnabled;
+}
+
 void GraphicsContext::setStrokePattern(Ref<Pattern>&& pattern)
 {
     m_state.strokeGradient.clear();
index e0bcfa5..0ed49ea 100644 (file)
@@ -114,6 +114,7 @@ namespace WebCore {
         GraphicsContextState()
             : shouldAntialias(true)
             , shouldSmoothFonts(true)
+            , antialiasedFontDilationEnabled(true)
             , shouldSubpixelQuantizeFonts(true)
             , paintingDisabled(false)
             , shadowsIgnoreTransforms(false)
@@ -156,6 +157,7 @@ namespace WebCore {
 
         bool shouldAntialias : 1;
         bool shouldSmoothFonts : 1;
+        bool antialiasedFontDilationEnabled : 1;
         bool shouldSubpixelQuantizeFonts : 1;
         bool paintingDisabled : 1;
         bool shadowsIgnoreTransforms : 1;
@@ -239,6 +241,9 @@ namespace WebCore {
         WEBCORE_EXPORT void setShouldAntialias(bool);
         bool shouldAntialias() const { return m_state.shouldAntialias; }
 
+        WEBCORE_EXPORT void setAntialiasedFontDilationEnabled(bool);
+        bool antialiasedFontDilationEnabled() const { return m_state.antialiasedFontDilationEnabled; }
+
         WEBCORE_EXPORT void setShouldSmoothFonts(bool);
         bool shouldSmoothFonts() const { return m_state.shouldSmoothFonts; }
 
index b36e060..eb7929c 100644 (file)
@@ -1045,6 +1045,7 @@ void PlatformCALayer::drawLayerContents(CGContextRef context, WebCore::PlatformC
     if (!layerContents->platformCALayerContentsOpaque()) {
         // Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
         graphicsContext.setShouldSmoothFonts(false);
+        graphicsContext.setAntialiasedFontDilationEnabled(true);
     }
     
 #if PLATFORM(MAC)
index 95e56fe..67a5ea0 100644 (file)
@@ -203,6 +203,26 @@ static void setCGFontRenderingMode(CGContextRef cgContext, NSFontRenderingMode r
 }
 #endif
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+static CGSize dilationSizeForTextColor(const Color& color)
+{
+    double hue;
+    double saturation;
+    double lightness;
+    color.getHSL(hue, saturation, lightness);
+    
+    // These values were derived empirically, and are only experimental.
+    if (lightness < 0.3333) // Dark
+        return CGSizeMake(0.007, 0.019);
+
+    if (lightness < 0.6667) // Medium
+        return CGSizeMake(0.032, 0.032);
+
+    // Light
+    return CGSizeMake(0.0475, 0.039);
+}
+#endif
+
 void FontCascade::drawGlyphs(GraphicsContext* context, const Font* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& anchorPoint) const
 {
     const FontPlatformData& platformData = font->platformData();
@@ -213,29 +233,34 @@ void FontCascade::drawGlyphs(GraphicsContext* context, const Font* font, const G
 
     bool shouldSmoothFonts;
     bool changeFontSmoothing;
+    bool matchAntialiasedAndSmoothedFonts = context->antialiasedFontDilationEnabled();
     
     switch (fontDescription().fontSmoothing()) {
     case Antialiased: {
         context->setShouldAntialias(true);
         shouldSmoothFonts = false;
         changeFontSmoothing = true;
+        matchAntialiasedAndSmoothedFonts = false; // CSS has opted into strictly antialiased fonts.
         break;
     }
     case SubpixelAntialiased: {
         context->setShouldAntialias(true);
         shouldSmoothFonts = true;
         changeFontSmoothing = true;
+        matchAntialiasedAndSmoothedFonts = true;
         break;
     }
     case NoSmoothing: {
         context->setShouldAntialias(false);
         shouldSmoothFonts = false;
         changeFontSmoothing = true;
+        matchAntialiasedAndSmoothedFonts = false;
         break;
     }
     case AutoSmoothing: {
         shouldSmoothFonts = true;
         changeFontSmoothing = false;
+        matchAntialiasedAndSmoothedFonts = true;
         break;
     }
     }
@@ -243,6 +268,7 @@ void FontCascade::drawGlyphs(GraphicsContext* context, const Font* font, const G
     if (!shouldUseSmoothing()) {
         shouldSmoothFonts = false;
         changeFontSmoothing = true;
+        matchAntialiasedAndSmoothedFonts = true;
     }
 
 #if !PLATFORM(IOS)
@@ -251,6 +277,17 @@ void FontCascade::drawGlyphs(GraphicsContext* context, const Font* font, const G
         originalShouldUseFontSmoothing = CGContextGetShouldSmoothFonts(cgContext);
         CGContextSetShouldSmoothFonts(cgContext, shouldSmoothFonts);
     }
+    
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+    CGFontAntialiasingStyle oldAntialiasingStyle;
+    bool resetAntialiasingStyle = false;
+    if (antialiasedFontDilationEnabled() && !CGContextGetShouldSmoothFonts(cgContext) && matchAntialiasedAndSmoothedFonts) {
+        resetAntialiasingStyle = true;
+        oldAntialiasingStyle = CGContextGetFontAntialiasingStyle(cgContext);
+        CGContextSetFontAntialiasingStyle(cgContext, kCGFontAntialiasingStyleUnfilteredCustomDilation);
+        CGContextSetFontDilation(cgContext, dilationSizeForTextColor(context->fillColor()));
+    }
+#endif
 #endif
 
 #if !PLATFORM(IOS)
@@ -368,6 +405,11 @@ void FontCascade::drawGlyphs(GraphicsContext* context, const Font* font, const G
         context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
 
 #if !PLATFORM(IOS)
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+    if (resetAntialiasingStyle)
+        CGContextSetFontAntialiasingStyle(cgContext, oldAntialiasingStyle);
+#endif
+    
     if (changeFontSmoothing)
         CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
 #endif
index 1fcb620..a705e55 100644 (file)
@@ -79,6 +79,9 @@ typedef uint32_t CGFontRenderingStyle;
 enum {
     kCGFontAntialiasingStyleUnfiltered = 0 << 7,
     kCGFontAntialiasingStyleFilterLight = 1 << 7,
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+    kCGFontAntialiasingStyleUnfilteredCustomDilation = (8 << 7),
+#endif
 };
 typedef uint32_t CGFontAntialiasingStyle;
 
@@ -126,6 +129,9 @@ void CGContextSetBaseCTM(CGContextRef, CGAffineTransform);
 void CGContextSetCTM(CGContextRef, CGAffineTransform);
 void CGContextSetCompositeOperation(CGContextRef, CGCompositeOperation);
 void CGContextSetShouldAntialiasFonts(CGContextRef, bool shouldAntialiasFonts);
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
+void CGContextSetFontDilation(CGContextRef, CGSize);
+#endif
 
 CFStringRef CGFontCopyFamilyName(CGFontRef);
 bool CGFontGetDescriptor(CGFontRef, CGFontDescriptor*);