Bug 215059

Summary: [Cocoa] Migrate from CTFontTransformGlyphsWithLanguage() to CTFontShapeGlyphs()
Product: WebKit Reporter: Myles C. Maxfield <mmaxfield>
Component: TextAssignee: Myles C. Maxfield <mmaxfield>
Status: RESOLVED FIXED    
Severity: Normal CC: benjamin, cdumez, cmarcelo, darin, dino, ews-watchlist, jonlee, koivisto, mmaxfield, simon.fraser, thorton, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 215051, 215053, 215057, 215333    
Bug Blocks: 206208, 214769    
Attachments:
Description Flags
WIP
none
WIP
none
WIP
none
WIP (Passes tests)
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
darin: review+
WIP
none
Rebased
none
Rebased
none
Rebased and addressed comments
none
Rebased and addressed comments
none
Patch for committing
none
Patch for committing
none
Patch for committing none

Description Myles C. Maxfield 2020-08-01 02:48:14 PDT
[Cocoa] Migrate from CTFontTransformGlyphsWithLanguage() to CTFontShapeGlyphs()
Comment 1 Myles C. Maxfield 2020-08-01 02:54:26 PDT
Created attachment 405781 [details]
WIP
Comment 2 Myles C. Maxfield 2020-08-04 01:00:59 PDT
Created attachment 405906 [details]
WIP
Comment 3 Myles C. Maxfield 2020-08-04 01:17:23 PDT
Regressions: Unexpected image-only failures (8)
  fast/ruby/ruby-expansion-cjk-2.html [ ImageOnlyFailure ]
  fast/ruby/ruby-expansion-cjk-4.html [ ImageOnlyFailure ]
  fast/ruby/ruby-expansion-cjk.html [ ImageOnlyFailure ]
  fast/text/isolate-ignore.html [ ImageOnlyFailure ]
  fast/text/ruby-justification-flush.html [ ImageOnlyFailure ]
  fast/text/soft-hyphen-min-preferred-width.html [ ImageOnlyFailure ]
  fast/text/vertical-displacement-simple-codepath.html [ ImageOnlyFailure ]
  imported/blink/fast/ruby/ruby-first-letter.html [ ImageOnlyFailure ]
Comment 4 Myles C. Maxfield 2020-08-04 01:54:19 PDT
Comment on attachment 405906 [details]
WIP

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

> Source/WebCore/platform/graphics/WidthIterator.cpp:243
>          if (font != lastFontData && width) {

the "&& width" part of this seems wrong.
Comment 5 Myles C. Maxfield 2020-08-04 02:07:02 PDT
Comment on attachment 405906 [details]
WIP

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

>> Source/WebCore/platform/graphics/WidthIterator.cpp:243
>>          if (font != lastFontData && width) {
> 
> the "&& width" part of this seems wrong.

Removing that part causes these tests to fail:

Regressions: Unexpected text-only failures (3)
  fast/text/soft-hyphen-2.html [ Failure ]
  fast/text/soft-hyphen-3.html [ Failure ]
  fast/text/soft-hyphen-4.html [ Failure ]

Regressions: Unexpected image-only failures (7)
  fast/ruby/ruby-expansion-cjk-2.html [ ImageOnlyFailure ]
  fast/ruby/ruby-expansion-cjk-4.html [ ImageOnlyFailure ]
  fast/ruby/ruby-expansion-cjk.html [ ImageOnlyFailure ]
  fast/text/ruby-justification-flush.html [ ImageOnlyFailure ]
  fast/text/soft-hyphen-min-preferred-width.html [ ImageOnlyFailure ]
  fast/text/vertical-displacement-simple-codepath.html [ ImageOnlyFailure ]
  imported/blink/fast/ruby/ruby-first-letter.html [ ImageOnlyFailure ]
Comment 6 Myles C. Maxfield 2020-08-04 02:12:58 PDT
Comment on attachment 405906 [details]
WIP

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

>>> Source/WebCore/platform/graphics/WidthIterator.cpp:243
>>>          if (font != lastFontData && width) {
>> 
>> the "&& width" part of this seems wrong.
> 
> Removing that part causes these tests to fail:
> 
> Regressions: Unexpected text-only failures (3)
>   fast/text/soft-hyphen-2.html [ Failure ]
>   fast/text/soft-hyphen-3.html [ Failure ]
>   fast/text/soft-hyphen-4.html [ Failure ]
> 
> Regressions: Unexpected image-only failures (7)
>   fast/ruby/ruby-expansion-cjk-2.html [ ImageOnlyFailure ]
>   fast/ruby/ruby-expansion-cjk-4.html [ ImageOnlyFailure ]
>   fast/ruby/ruby-expansion-cjk.html [ ImageOnlyFailure ]
>   fast/text/ruby-justification-flush.html [ ImageOnlyFailure ]
>   fast/text/soft-hyphen-min-preferred-width.html [ ImageOnlyFailure ]
>   fast/text/vertical-displacement-simple-codepath.html [ ImageOnlyFailure ]
>   imported/blink/fast/ruby/ruby-first-letter.html [ ImageOnlyFailure ]

The 3 new failures look like they are rebaselines.

fast/text/soft-hyphen-2.html [ Failure ]
fast/text/soft-hyphen-3.html [ Failure ]
fast/text/soft-hyphen-4.html [ Failure ]
Comment 7 Myles C. Maxfield 2020-08-04 02:19:24 PDT
Comment on attachment 405906 [details]
WIP

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

> Source/WebCore/platform/graphics/WidthIterator.cpp:125
>          advances[i].setHeight(-advances[i].height());

We need to do the same thing to the origins, too.
Comment 8 Myles C. Maxfield 2020-08-04 02:30:16 PDT
Created attachment 405909 [details]
WIP
Comment 9 Myles C. Maxfield 2020-08-04 03:18:33 PDT
Created attachment 405912 [details]
WIP (Passes tests)
Comment 10 Myles C. Maxfield 2020-08-04 17:37:08 PDT
Created attachment 405966 [details]
Patch
Comment 11 Myles C. Maxfield 2020-08-04 17:37:39 PDT
Created attachment 405967 [details]
Patch
Comment 12 Myles C. Maxfield 2020-08-04 20:12:09 PDT
Created attachment 405978 [details]
Patch
Comment 13 Myles C. Maxfield 2020-08-04 21:05:58 PDT
Comment on attachment 405978 [details]
Patch

I should do some performance testing before marking this as r?.
Comment 14 Myles C. Maxfield 2020-08-04 22:12:21 PDT
Comment on attachment 405978 [details]
Patch

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

> Source/WebCore/platform/graphics/cocoa/FontCocoa.mm:590
> +        glyphBuffer.offsetsInString(beginningGlyphIndex)[beginningGlyphIndex + i] += beginningStringIndex;

beginningGlyphIndex is listed twice
Comment 15 Myles C. Maxfield 2020-08-06 12:33:32 PDT
Created attachment 406101 [details]
Patch
Comment 16 Myles C. Maxfield 2020-08-06 17:03:30 PDT
Created attachment 406134 [details]
Patch
Comment 17 Myles C. Maxfield 2020-08-06 17:05:51 PDT
Created attachment 406135 [details]
Patch
Comment 18 Myles C. Maxfield 2020-08-07 04:00:56 PDT
$ compare-results -a ~/Build-Vanilla/Products/Release/plt-results-1596796412 -b ~/Build-CTFontShapeGlyphs/Products/Release/plt-results-1596797276 
a mean = 741.00884
b mean = 736.28295
pValue = 0.7559888497
(Smaller means are better.)
1.006 times better
Results ARE NOT significant
Comment 19 Radar WebKit Bug Importer 2020-08-08 02:49:16 PDT
<rdar://problem/66721009>
Comment 20 Darin Adler 2020-08-08 11:39:03 PDT
Comment on attachment 406135 [details]
Patch

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

> Source/WebCore/platform/graphics/FontCascade.h:119
> +    float widthForSimpleText(StringView text, TextDirection = TextDirection::LTR /* matches default argument of TextRun constructor */) const;

Why does it matter that these defaults match?

> Source/WebCore/platform/graphics/TextRun.h:46
> +    // LTR default argument matches FontCascade::widthForSimpleText()'s default argument

Need period at end of comment.

Why does it matter that these defaults match?

> Source/WebCore/platform/graphics/TextRun.h:63
> +    // LTR default argument matches FontCascade::widthForSimpleText()'s default argument

Need period at end of comment.

Why does it matter that these defaults match?

> Source/WebCore/platform/graphics/WidthIterator.cpp:116
> +    // CTFontTransformGlyphs() operates in visual order, but WidthIterator iterates in logical order.
> +    // Temporarily put us in visual order just for the call, then put us back into logical order when
> +    // the call is done.
> +    // We don't have a global view of the entire GlyphBuffer; we're just operating on a single chunk of it.
> +    // WidthIterator encounters the chunks out in logical order, so we have to maintain that invariant.
> +    // Eventually, FontCascade::layoutSimpleText() will reverse the whole buffer to put the entire thing
> +    // in visual order, but that's okay because it has a view of the entire GlyphBuffer.
> +    // On the other hand, CTFontShapeGlyphs() accepts the buffer in logical order but returns it in physical
> +    // order, which means the second reverse() in this function still needs to execute when
> +    // CTFontShapeGlyphs() is being used.
> +#if !USE(CTFONTSHAPEGLYPHS)

This is strange. It’s cross platform code, but the comment seems to imply that all platforms use either CTFontTransformGlyphs or CTFontShapeGlyphs. Can we create some kind of cross-platform abstraction here? Typically the cross-platform code doesn’t need long comments about the specific platform-dependent functions used. In modern code could even do something like:

    if constexpr (Font::applyTransformsTakesGlyphsInVisualOrder)

Maybe it’s "CTFontTransformGlyphs and all the other functions used for this purpose on all the other platforms?"

> LayoutTests/ChangeLog:13
> +        * fast/text/soft-hyphen-2-expected.txt: Removed. Platform-specific rendertree dumps
> +        need to be in platform/ subfolders.
> +        * fast/text/soft-hyphen-3-expected.txt: Removed.
> +        * fast/text/soft-hyphen-4-expected.txt: Removed.

Can any of these tests be changed into ref tests?
Comment 21 Myles C. Maxfield 2020-08-08 23:29:41 PDT
Created attachment 406263 [details]
WIP

Some tests are failing on Big Sur that aren't failing on Catalina. (EWS doesn't run on Big Sur so it didn't catch them.) I'm investigating now.
Comment 22 Myles C. Maxfield 2020-08-09 17:46:26 PDT
Comment on attachment 406135 [details]
Patch

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

>> Source/WebCore/platform/graphics/FontCascade.h:119
>> +    float widthForSimpleText(StringView text, TextDirection = TextDirection::LTR /* matches default argument of TextRun constructor */) const;
> 
> Why does it matter that these defaults match?

There are a few places in WebKit where we have things like:

if (canUseSimplePath)
    result = font.widthForSimpleText(theString);
else {
    TextRun textRun(theString);
    result = font.width(run);
}

The TextDirection argument to TextRun's constructor needs to match the TextDirection argument to widthForSimpleText(). Both arguments have default values, though.
Comment 23 Myles C. Maxfield 2020-08-09 17:50:30 PDT
Created attachment 406276 [details]
Rebased
Comment 24 Darin Adler 2020-08-09 18:02:01 PDT
Comment on attachment 406135 [details]
Patch

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

>>> Source/WebCore/platform/graphics/FontCascade.h:119
>>> +    float widthForSimpleText(StringView text, TextDirection = TextDirection::LTR /* matches default argument of TextRun constructor */) const;
>> 
>> Why does it matter that these defaults match?
> 
> There are a few places in WebKit where we have things like:
> 
> if (canUseSimplePath)
>     result = font.widthForSimpleText(theString);
> else {
>     TextRun textRun(theString);
>     result = font.width(run);
> }
> 
> The TextDirection argument to TextRun's constructor needs to match the TextDirection argument to widthForSimpleText(). Both arguments have default values, though.

Sure, but "left to right" being the default, while possibly culturally biased, hardly needs a comment citing some particular other function where we often use the same default, even if idiomatically they are often used side by side or interchangeably as above. The comment just doesn’t add much; not even obvious why it’s relevant from the way it’s written.
Comment 25 Myles C. Maxfield 2020-08-09 22:35:28 PDT
Created attachment 406282 [details]
Rebased
Comment 26 Myles C. Maxfield 2020-08-10 02:22:08 PDT
I see what's happening. The old code had a bug where, if the last character in the run had a 0 width and was a fallback font, it wouldn't get added to m_fallbackFonts.
Comment 27 Myles C. Maxfield 2020-08-10 02:39:11 PDT
(In reply to Myles C. Maxfield from comment #26)
> I see what's happening. The old code had a bug where, if the last character
> in the run had a 0 width and was a fallback font, it wouldn't get added to
> m_fallbackFonts.

** There's a sequence of fallback characters, each of which has 0 width.

Also, this is doubly bad because the glyphIDs from the fallback characters would get shaped with the wrong font :(
Comment 28 Myles C. Maxfield 2020-08-10 03:06:52 PDT
Created attachment 406289 [details]
Rebased and addressed comments
Comment 29 Myles C. Maxfield 2020-08-10 04:02:26 PDT
Created attachment 406291 [details]
Rebased and addressed comments
Comment 30 Myles C. Maxfield 2020-08-10 15:19:12 PDT
Created attachment 406332 [details]
Patch for committing
Comment 31 Myles C. Maxfield 2020-08-10 15:20:49 PDT
Created attachment 406333 [details]
Patch for committing
Comment 32 Myles C. Maxfield 2020-08-10 17:24:37 PDT
Looks like imported/blink/fast/text/international/kana-voiced-sound-marks.html passes on Catalina and Big Sur, but not on Mojave. I'll investigate.
Comment 33 Myles C. Maxfield 2020-08-10 21:05:42 PDT
Created attachment 406358 [details]
Patch for committing
Comment 34 Myles C. Maxfield 2020-08-10 21:24:00 PDT
Committed r265487: <https://trac.webkit.org/changeset/265487>