Bug 138683 - platform/mac/editing/input/devanagari-ligature.html is flaky on Yosemite, ligature fails to form
Summary: platform/mac/editing/input/devanagari-ligature.html is flaky on Yosemite, lig...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Text (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Myles C. Maxfield
URL:
Keywords: InRadar
: 138075 (view as bug list)
Depends on:
Blocks:
 
Reported: 2014-11-12 21:00 PST by Alexey Proskuryakov
Modified: 2015-01-31 00:52 PST (History)
3 users (show)

See Also:


Attachments
tests.txt (74.42 KB, text/plain)
2014-11-12 21:00 PST, Alexey Proskuryakov
no flags Details
tests.txt (1.31 KB, text/plain)
2014-11-12 23:22 PST, Alexey Proskuryakov
no flags Details
Patch (4.20 KB, patch)
2014-11-14 11:18 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (4.38 KB, patch)
2014-11-14 11:46 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (4.38 KB, patch)
2014-11-14 11:58 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (6.96 KB, patch)
2014-11-18 17:15 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (10.60 KB, patch)
2014-12-22 14:25 PST, Myles C. Maxfield
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexey Proskuryakov 2014-11-12 21:00:40 PST
Created attachment 241465 [details]
tests.txt

platform/mac/editing/input/devanagari-ligature.html is flaky on bots, and I can reproduce 100% reliably locally.

The failure shows correct Unicode content, but with a wrong width, meaning that a ligature failed to form at text drawing time I think.

Steps to reproduce with attached tests.txt:

run-webkit-tests --test-list=tests.txt --child-processes=1 --no-retry

-        RenderText {#text} at (0,4) size 12x18
-          text run at (0,4) width 12: "\x{915}\x{94D}\x{937}"
+        RenderText {#text} at (0,4) size 21x18
+          text run at (0,4) width 21: "\x{915}\x{94D}\x{937}"

It runs ~1500 tests before this one, and I cannot reduce the list much further. So, it's not just that some previous test breaks this one, it looks more like some cache or table overflows and text machinery starts to misbehave.
Comment 1 Alexey Proskuryakov 2014-11-12 23:22:30 PST
Created attachment 241475 [details]
tests.txt

OK, reduced that to 33 tests. Probably not much help for analysis, but at least it can now be reproduced quickly.
Comment 2 Myles C. Maxfield 2014-11-13 14:41:53 PST
Can reproduce on my cheese grater (with --child-processes=1)
Comment 3 Myles C. Maxfield 2014-11-14 01:16:39 PST
SimpleFontData::canRenderCombiningCharacterSequence() is returning different answers
Comment 4 Myles C. Maxfield 2014-11-14 01:18:13 PST
The font in question is "ITFDevanagari-Book" and the code point sequence in question is U+0915 U+094D
Comment 5 Myles C. Maxfield 2014-11-14 01:30:16 PST
Disabling the cache in SimpleFontData::canRenderCombiningCharacterSequence() seems to fix this
Comment 6 Myles C. Maxfield 2014-11-14 10:30:44 PST
This is because CFEqual() on CGFontRefs is a raw pointer compare instead of deep introspection. CTFontCopyGraphicsFont() uses an internal cache, so the pointer compare will fail or succeed based on whether or not the font happens to already be in the internal cache
Comment 7 Myles C. Maxfield 2014-11-14 11:18:54 PST
Created attachment 241600 [details]
Patch
Comment 8 Alexey Proskuryakov 2014-11-14 11:26:48 PST
Comment on attachment 241600 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=241600&action=review

Nicely done!

Leaving this for someone who knows about fonts to review though.

> Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm:509
> +        RetainPtr<CFURLRef> runUrl = adoptCF(static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(runFontDescriptor.get(), kCTFontReferenceURLAttribute)));

WebKit style for this name is "runURL".

I wonder if this attribute is always guaranteed to be non-null and unique.
Comment 9 Myles C. Maxfield 2014-11-14 11:44:17 PST
Comment on attachment 241600 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=241600&action=review

>> Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm:509
>> +        RetainPtr<CFURLRef> runUrl = adoptCF(static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(runFontDescriptor.get(), kCTFontReferenceURLAttribute)));
> 
> WebKit style for this name is "runURL".
> 
> I wonder if this attribute is always guaranteed to be non-null and unique.

It is. WebFonts will look like "file://iNmEmOrYcGfOnT_0x7f8220cef460#postscript-name=DroidSansFallback" However, note the pointer inside the name. This means that the original bug will still exist for these fonts. I'll put a FIXME in the code.
Comment 10 Myles C. Maxfield 2014-11-14 11:46:58 PST
Created attachment 241607 [details]
Patch
Comment 11 Myles C. Maxfield 2014-11-14 11:55:45 PST
(In reply to comment #9)
> Comment on attachment 241600 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=241600&action=review
> 
> >> Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm:509
> >> +        RetainPtr<CFURLRef> runUrl = adoptCF(static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(runFontDescriptor.get(), kCTFontReferenceURLAttribute)));
> > 
> > WebKit style for this name is "runURL".
> > 
> > I wonder if this attribute is always guaranteed to be non-null and unique.
> 
> It is. WebFonts will look like
> "file://iNmEmOrYcGfOnT_0x7f8220cef460#postscript-name=DroidSansFallback"
> However, note the pointer inside the name. This means that the original bug
> will still exist for these fonts. I'll put a FIXME in the code.

Ultimately, there's no way to do a reliable deep compare for all CTFontRefs, and <rdar://problem/18985642> is about this
Comment 12 Myles C. Maxfield 2014-11-14 11:58:59 PST
Created attachment 241613 [details]
Patch
Comment 13 Alexey Proskuryakov 2014-11-14 16:14:59 PST
FWIW, I cannot reproduce on OS X Mavericks with the same list of 33 tests.
Comment 14 Myles C. Maxfield 2014-11-14 16:15:40 PST
Please try the longer list. My laptop can only reproduce on the longer list, not the shorter one.
Comment 15 Alexey Proskuryakov 2014-11-14 16:42:04 PST
Cannot reproduce on Mavericks with the long list either.
Comment 16 Radar WebKit Bug Importer 2014-11-18 14:20:58 PST
<rdar://problem/19020875>
Comment 17 Myles C. Maxfield 2014-11-18 17:15:34 PST
Created attachment 241835 [details]
Patch
Comment 18 Alexey Proskuryakov 2014-12-04 09:18:40 PST
Ping?
Comment 19 Myles C. Maxfield 2014-12-04 10:05:04 PST
The earliest I'll be able to investigate this is Monday.
Comment 20 Myles C. Maxfield 2014-12-19 20:03:08 PST
This is ultimately caused by <rdar://problem/19316856>
Comment 21 Myles C. Maxfield 2014-12-22 12:58:40 PST
We should probably only do this on 10.10 and below.
Comment 22 mitz 2014-12-22 13:12:26 PST
Comment on attachment 241835 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=241835&action=review

The pattern of using a CTFont’s underlying CGFont for comparison occurs in ComplexTextController::collectComplexTextRunsForCharacters too, so I think it should be fixed there as well. Additionally, if the problematic CTFontCopyGraphicsFont behavior is specific to some OS versions, then the workaround should only be used when building for those versions..

> Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp:129
> +            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=138683 This is a shallow pointer compare for web fonts
> +            // which means we might erroneously return false here

What does this mean? If the objects are CFURLs as you assert above, how can CFEqual be comparing them differently than it compares other URLs?
Comment 23 Myles C. Maxfield 2014-12-22 14:25:22 PST
Created attachment 243642 [details]
Patch
Comment 24 Darin Adler 2014-12-22 22:46:46 PST
Comment on attachment 243642 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=243642&action=review

> Source/WebCore/platform/graphics/FontPlatformData.h:124
> +    static RetainPtr<CFTypeRef> objectForEqualityCheck(CTFontRef);
> +    RetainPtr<CFTypeRef> objectForEqualityCheck() const;

This seems a bit clumsy, but I guess it’s OK.

> Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm:296
> +    RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontCopyFontDescriptor(ctFont));

Consider auto for the type here?

> Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm:309
> +    return FontPlatformData::objectForEqualityCheck(ctFont());

No need for the FontPlatformData:: prefix here.

> Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp:124
> +            RetainPtr<CFTypeRef> runFontEqualityObject = FontPlatformData::objectForEqualityCheck(runFont);

Do we need this local variable?

> Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm:496
> +        RetainPtr<CFTypeRef> runFontEqualityObject = FontPlatformData::objectForEqualityCheck(runFont);

Do we need this local variable?
Comment 25 Myles C. Maxfield 2014-12-23 10:51:15 PST
Comment on attachment 243642 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=243642&action=review

>> Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm:296
>> +    RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontCopyFontDescriptor(ctFont));
> 
> Consider auto for the type here?

Done.

>> Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm:309
>> +    return FontPlatformData::objectForEqualityCheck(ctFont());
> 
> No need for the FontPlatformData:: prefix here.

Done.

>> Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp:124
>> +            RetainPtr<CFTypeRef> runFontEqualityObject = FontPlatformData::objectForEqualityCheck(runFont);
> 
> Do we need this local variable?

Done.

>> Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm:496
>> +        RetainPtr<CFTypeRef> runFontEqualityObject = FontPlatformData::objectForEqualityCheck(runFont);
> 
> Do we need this local variable?

Done.
Comment 26 Myles C. Maxfield 2014-12-23 11:23:52 PST
Committed r177689: <http://trac.webkit.org/changeset/177689>
Comment 27 Alexey Proskuryakov 2014-12-26 16:26:05 PST
*** Bug 138075 has been marked as a duplicate of this bug. ***
Comment 28 mitz 2015-01-31 00:52:29 PST
Comment on attachment 243642 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=243642&action=review

> Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm:259
> +                    if (CFEqual(runFontEqualityObject.get(), runFontEqualityObject.get()))

Whoops, this is a tautology! It caused bug 141112.