<rdar://problem/10191243> Glyph variants (line final swashes) appear where they shoul...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Sep 2011 20:21:02 +0000 (20:21 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Sep 2011 20:21:02 +0000 (20:21 +0000)
Reviewed by Simon Fraser.

Source/WebCore:

Test: fast/text/line-initial-and-final-swashes.html

Hoefler Text Italic enables line-initial and -final swashes by default, so disable them. This
change targets only this known-bad font rather than all fonts, because at least one font (Khmer MN)
incorrectly claims to have the line-initial feature enabled, but disabling it actually does
something different and bad (breaking some combining marks).

* platform/graphics/cocoa/FontPlatformDataCocoa.mm:
(WebCore::createFeatureSettingDictionary): Added this helper function.
(WebCore::cascadeToLastResortFontDescriptor): Deployed WTF_ARRAY_LENGTH().
(WebCore::cascadeToLastResortAndDisableSwashesFontDescriptor): Added. Returns a font descriptor
that, in addition to having a cascade list consisting of the last resort font, also has feature
settings to disable line-initial and line-final swashes.
(WebCore::FontPlatformData::ctFont): For Hoefler Text Italic, use cascadeToLastResortAndDisableSwashesFontDescriptor().

LayoutTests:

* fast/text/line-initial-and-final-swashes.html: Added.
* platform/mac/fast/text/line-initial-and-final-swashes-expected.png: Added.
* platform/mac/fast/text/line-initial-and-final-swashes-expected.txt: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/text/line-initial-and-final-swashes.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm

index 308450a..0a63905 100644 (file)
@@ -1,3 +1,13 @@
+2011-09-29  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10191243> Glyph variants (line final swashes) appear where they should not
+
+        Reviewed by Simon Fraser.
+
+        * fast/text/line-initial-and-final-swashes.html: Added.
+        * platform/mac/fast/text/line-initial-and-final-swashes-expected.png: Added.
+        * platform/mac/fast/text/line-initial-and-final-swashes-expected.txt: Added.
+
 2011-09-29  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r96340.
diff --git a/LayoutTests/fast/text/line-initial-and-final-swashes.html b/LayoutTests/fast/text/line-initial-and-final-swashes.html
new file mode 100644 (file)
index 0000000..aa49e29
--- /dev/null
@@ -0,0 +1,7 @@
+<p>
+    The blue text should be identical to, and overlap, the red text, so there should be no red pixels below.
+</p>
+<div style="font-size: 144px; font-family: Hoefler Text; font-style: italic; -webkit-font-smoothing: none;">
+    <div style="color: red;">v a&#x0300; e</div>
+    <div style="margin-top: -144px;">v &#xe0; e</div>
+</div>
diff --git a/LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.png b/LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.png
new file mode 100644 (file)
index 0000000..bcf3cea
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.txt b/LayoutTests/platform/mac/fast/text/line-initial-and-final-swashes-expected.txt
new file mode 100644 (file)
index 0000000..1910ef9
--- /dev/null
@@ -0,0 +1,15 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x18
+        RenderText {#text} at (0,0) size 635x18
+          text run at (0,0) width 635: "The blue text should be identical to, and overlap, the red text, so there should be no red pixels below."
+      RenderBlock {DIV} at (0,34) size 784x144
+        RenderBlock {DIV} at (0,0) size 784x144 [color=#FF0000]
+          RenderText {#text} at (0,0) size 256x144
+            text run at (0,0) width 256: "v a\x{300} e"
+        RenderBlock {DIV} at (0,0) size 784x144
+          RenderText {#text} at (0,0) size 256x144
+            text run at (0,0) width 256: "v \x{E0} e"
index fa6c59b..54df607 100644 (file)
@@ -1,3 +1,24 @@
+2011-09-29  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10191243> Glyph variants (line final swashes) appear where they should not
+
+        Reviewed by Simon Fraser.
+
+        Test: fast/text/line-initial-and-final-swashes.html
+
+        Hoefler Text Italic enables line-initial and -final swashes by default, so disable them. This
+        change targets only this known-bad font rather than all fonts, because at least one font (Khmer MN)
+        incorrectly claims to have the line-initial feature enabled, but disabling it actually does
+        something different and bad (breaking some combining marks).
+
+        * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
+        (WebCore::createFeatureSettingDictionary): Added this helper function.
+        (WebCore::cascadeToLastResortFontDescriptor): Deployed WTF_ARRAY_LENGTH().
+        (WebCore::cascadeToLastResortAndDisableSwashesFontDescriptor): Added. Returns a font descriptor
+        that, in addition to having a cascade list consisting of the last resort font, also has feature
+        settings to disable line-initial and line-final swashes.
+        (WebCore::FontPlatformData::ctFont): For Hoefler Text Italic, use cascadeToLastResortAndDisableSwashesFontDescriptor().
+
 2011-09-29  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         Unreviewed: resetting baseline for code generator bindings
index 1d344fd..906405b 100644 (file)
@@ -176,6 +176,17 @@ inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant)
     return TextSpacingProportional;
 }
 
+static CFDictionaryRef createFeatureSettingDictionary(int featureTypeIdentifier, int featureSelectorIdentifier)
+{
+    RetainPtr<CFNumberRef> featureTypeIdentifierNumber(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureTypeIdentifier));
+    RetainPtr<CFNumberRef> featureSelectorIdentifierNumber(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorIdentifier));
+
+    const void* settingKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey };
+    const void* settingValues[] = { featureTypeIdentifierNumber.get(), featureSelectorIdentifierNumber.get() };
+
+    return CFDictionaryCreate(kCFAllocatorDefault, settingKeys, settingValues, WTF_ARRAY_LENGTH(settingKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+}
+
 static CTFontDescriptorRef cascadeToLastResortFontDescriptor()
 {
     static CTFontDescriptorRef descriptor;
@@ -184,14 +195,35 @@ static CTFontDescriptorRef cascadeToLastResortFontDescriptor()
 
     const void* keys[] = { kCTFontCascadeListAttribute };
     const void* descriptors[] = { CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0) };
-    const void* values[] = { CFArrayCreate(kCFAllocatorDefault, descriptors, sizeof(descriptors) / sizeof(*descriptors), &kCFTypeArrayCallBacks) };
-    RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(*keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    const void* values[] = { CFArrayCreate(kCFAllocatorDefault, descriptors, WTF_ARRAY_LENGTH(descriptors), &kCFTypeArrayCallBacks) };
+    RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
 
     descriptor = CTFontDescriptorCreateWithAttributes(attributes.get());
 
     return descriptor;
 }
 
+static CTFontDescriptorRef cascadeToLastResortAndDisableSwashesFontDescriptor()
+{
+    static CTFontDescriptorRef descriptor;
+    if (descriptor)
+        return descriptor;
+
+    RetainPtr<CFDictionaryRef> lineInitialSwashesOffSetting(AdoptCF, createFeatureSettingDictionary(kSmartSwashType, kLineInitialSwashesOffSelector));
+    RetainPtr<CFDictionaryRef> lineFinalSwashesOffSetting(AdoptCF, createFeatureSettingDictionary(kSmartSwashType, kLineFinalSwashesOffSelector));
+
+    const void* settingDictionaries[] = { lineInitialSwashesOffSetting.get(), lineFinalSwashesOffSetting.get() };
+    RetainPtr<CFArrayRef> featureSettings(AdoptCF, CFArrayCreate(kCFAllocatorDefault, settingDictionaries, WTF_ARRAY_LENGTH(settingDictionaries), &kCFTypeArrayCallBacks));
+
+    const void* keys[] = { kCTFontFeatureSettingsAttribute };
+    const void* values[] = { featureSettings.get() };
+    RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+
+    descriptor = CTFontDescriptorCreateCopyWithAttributes(cascadeToLastResortFontDescriptor(), attributes.get());
+
+    return descriptor;
+}
+
 // Adding a cascade list breaks the font on Leopard
 static bool canSetCascadeListForCustomFont()
 {
@@ -216,9 +248,16 @@ CTFontRef FontPlatformData::ctFont() const
         return m_CTFont.get();
 
     m_CTFont = toCTFontRef(m_font);
-    if (m_CTFont)
-        m_CTFont.adoptCF(CTFontCreateCopyWithAttributes(m_CTFont.get(), m_size, 0, cascadeToLastResortFontDescriptor()));
-    else
+    if (m_CTFont) {
+        CTFontDescriptorRef fontDescriptor;
+        RetainPtr<CFStringRef> postScriptName(AdoptCF, CTFontCopyPostScriptName(m_CTFont.get()));
+        // Hoefler Text Italic has line-initial and -final swashes enabled by default, so disable them.
+        if (CFEqual(postScriptName.get(), CFSTR("HoeflerText-Italic")))
+            fontDescriptor = cascadeToLastResortAndDisableSwashesFontDescriptor();
+        else
+            fontDescriptor = cascadeToLastResortFontDescriptor();
+        m_CTFont.adoptCF(CTFontCreateCopyWithAttributes(m_CTFont.get(), m_size, 0, fontDescriptor));
+    } else
         m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, canSetCascadeListForCustomFont() ? cascadeToLastResortFontDescriptor() : 0));
 
     if (m_widthVariant != RegularWidth) {