Title: [281378] trunk
Revision
281378
Author
mmaxfi...@apple.com
Date
2021-08-21 12:18:51 -0700 (Sat, 21 Aug 2021)

Log Message

[Cocoa] Single characters don't get shaped in the fast text codepath
https://bugs.webkit.org/show_bug.cgi?id=186804

Reviewed by Alan Bujtas.

Source/WebCore:

Previously, single characters weren't shaped in the fast text codepath,
because shaping in the fast text codepath was just for kerning and
ligatures. Kerning didn't need to shape individual characters because
kerning only applies to pairs of characters, and ligatures didn't need
to shape individual characters because two characters are required to
form a ligature. However, now that we want to replace the complex text
codepath with a new-and-improved fast text codepath, we have to perform
all shaping in the fast text codepath, regardless of how many characters
are present.

Test: fast/text/single-character-shaping.html

* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::applyFontTransforms):
(WebCore::WidthIterator::commitCurrentFontRange):
(WebCore::WidthIterator::advanceInternal):
(WebCore::WidthIterator::shouldApplyFontTransforms const): Deleted.
* platform/graphics/WidthIterator.h:
* platform/graphics/coretext/FontCoreText.cpp:
(WebCore::Font::applyTransforms): Keep kerning disabled for single glyphs,
because of performance. This will be able to be removed when rdar://82195405
is fixed.
* rendering/mathml/RenderMathMLOperator.cpp:
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths):

Tools:

Huge thanks to Laurence Penney to contributing this test font!!!

* Scripts/webkitpy/common/config/contributors.json:

LayoutTests:

Huge thanks to Laurence Penney to contributing this test font!!!

* fast/text/resources/UniversTofu-GSUB-rvrn.ttf: Added. The license is Apache 2.0.
* fast/text/single-character-shaping-expected.html: Added.
* fast/text/single-character-shaping.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281377 => 281378)


--- trunk/LayoutTests/ChangeLog	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/LayoutTests/ChangeLog	2021-08-21 19:18:51 UTC (rev 281378)
@@ -1,3 +1,16 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Single characters don't get shaped in the fast text codepath
+        https://bugs.webkit.org/show_bug.cgi?id=186804
+
+        Reviewed by Alan Bujtas.
+
+        Huge thanks to Laurence Penney to contributing this test font!!!
+
+        * fast/text/resources/UniversTofu-GSUB-rvrn.ttf: Added. The license is Apache 2.0.
+        * fast/text/single-character-shaping-expected.html: Added.
+        * fast/text/single-character-shaping.html: Added.
+
 2021-08-21  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Enable Array#findLast method

Added: trunk/LayoutTests/fast/text/resources/UniversTofu-GSUB-rvrn.ttf (0 => 281378)


--- trunk/LayoutTests/fast/text/resources/UniversTofu-GSUB-rvrn.ttf	                        (rev 0)
+++ trunk/LayoutTests/fast/text/resources/UniversTofu-GSUB-rvrn.ttf	2021-08-21 19:18:51 UTC (rev 281378)
@@ -0,0 +1,24 @@
+\x80pDSIG4GSUB@D\xDF\xDET0OS/2hg\xBCx`STAT\xF0\xF9\xDD\xF6\x84$cmaps\xD0\xD0Zfvar\xF6\xDE\xFF\xA88glyfI8\xC7\xE1\xB8\xECgvarT32D\xE0TheadOL\xB0\xFC6hhea\xF24$hmtx\x83+\xE9\xD8\xF8loca\xE4\xE4,\x8Amaxp\xB56X name\x96o\xCFD\xA4\xFFpost5\x8Dz$\xA4\xB0\xC1\xFEt_<\xF5\xE8\xD6\xF2f2\xD6\xF2\xA2\xE6K\xFF\xF8\xBC\xE8\xFF8XK8DdW\x90\x8AXK\x8AX^2,UKWN@ z \xFF8\xC8\xE8\xC8\xF4\xBC SKXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXMSXXXXXSKXF .9Zz\xFF\xFF ,0Aa\xFF\xFF\xFF
 \xE1\xFF\xC1\xFF\xBB
+BCA((((((((((((((((((((((((((((((((((((((((((((((((NNNNNNvvvvvvvvvvvvvvK\xBC!!%!'K\xBD\xFEC\x8E\xFE\x9Dn(\xFE\x93.(n'\xBC\xFDD-b\xFD\x9Ex\xFD\x85{\xFD\x85{S\xFF\xF8\xFA\xE4326653#5#"&&5\xAE5C 7![[+(=(/N2\xE4\xFE\xD0B36&,\xFEG#!K:FK\xBC!!%!'K\xBD\xFEC\x8E\xFE\x9Dn(\xFE\x93.(n'\xBC\xFDD-b\xFD\x9Ex\xFD\x85{\xFD\x85{\xBA1+ER	e	}	<\x8B	(\xC7	\xEF	&		/	
+;	}Univers TofuRegular1.000;UKWN;UniversTofu-RegularUnivers Tofu RegularVersion 1.000UniversTofu-RegularUnivers TofuRegular1.000;UKWN;UniversTofu-RegularUnivers Tofu RegularVersion 1.000UniversTofu-RegularWeightWidth\xFF\xB52D$%&'()*+,-./0123456789:;<=DEFGHIJKLMNOPQRSTUVWXYZ[\]u.alt"<lDFLT\xFF\xFFrvrnzero\xFF\xFA600\xB2J\xB2d\xB2
 ~\xB2\x98\xB2
+\xC0\xC1H\xC1H@
+\xC0\xE0 @
+f@\xC0\xC1H
+,\xCD@\xC0\xF9\x9A
+>\xB8@\xC0f$wghtwdthwght\xC8\x90\x84wdth2d\xC8\x9ED\xB2\xB6\xB6\xB6\xB6\xB6\xB6\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1\xD1@\xC0@\xC0\xC0\xC0     \x90\x81\x93\x90\x81\x93\x90\x81\x93\x90\x81\x93\x90\xFB\x81\x937 2 = C 4 B\x8C\x8C\x8CpG5\xF6\xF6\xF6xx\xF6\xF6\xF6
+
+
+@\x82\x81\x80\xF4
+	\xF9\xF0\x83\xEC\xEC\xF7\x82
+\x84\xE6\xE6\xE6\xFB
++\xD8\xD8!\xF6\x81\x80\xF8\xDD\xDD\xDD\xE9(\x83\x84
+
+
+36FjB\x84\x84\x83}}B\x83\x83\x80r[K1
+
+
+@\x87\x81\x81\xED\xED\xED)G\x83\xF9\xF9\xF9	
+\x84\xD5\xD5ձ\x81L\xFFo\xFFI\xFF1\xFF1\xFF1\xFF1\xFF1\xFF4\xFF4\xFF:\xFFM\xFFj\xFF|\x8B\xB6\xD5\xD5\xD5@\xFE쁀\xBD\xE4\xFD\xFD\xFD\xECκ\x83\xF1\xF4\xFC\xEF̹\x84\xE9\xE9\xE9\xD7\xCAŽ\xB5\xB5\xB6\xB5\xB5\xB4\xB4\xB7\xB7\xC4\xD9\xE8\xEE\xEC\xEC\xEA@)\x81\x80\xD7\xE6\xF6ѱ\x83\xC4\xDA\xF0\xFD\xFF\xFC\xECބ     \x90\x81\x93\x90\x81\x93\x90\x81\x93\x90\x81\x93\x90\xFB\x81\x93
\ No newline at end of file

Added: trunk/LayoutTests/fast/text/single-character-shaping-expected.html (0 => 281378)


--- trunk/LayoutTests/fast/text/single-character-shaping-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/single-character-shaping-expected.html	2021-08-21 19:18:51 UTC (rev 281378)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "WebFont";
+    src: url("resources/UniversTofu-GSUB-rvrn.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+This test makes sure that individual characters are shaped in the fast text codepath. The test passes if you see a box with an X through it below.
+<div style="font: 48px 'WebFont'; font-weight: 200; font-stretch: 200%; font-feature-settings: 'ABCD';">u</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/text/single-character-shaping.html (0 => 281378)


--- trunk/LayoutTests/fast/text/single-character-shaping.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/single-character-shaping.html	2021-08-21 19:18:51 UTC (rev 281378)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "WebFont";
+    src: url("resources/UniversTofu-GSUB-rvrn.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+This test makes sure that individual characters are shaped in the fast text codepath. The test passes if you see a box with an X through it below.
+<div style="font: 48px 'WebFont'; font-weight: 200; font-stretch: 200%;">u</div>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (281377 => 281378)


--- trunk/Source/WebCore/ChangeLog	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Source/WebCore/ChangeLog	2021-08-21 19:18:51 UTC (rev 281378)
@@ -1,3 +1,35 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Single characters don't get shaped in the fast text codepath
+        https://bugs.webkit.org/show_bug.cgi?id=186804
+
+        Reviewed by Alan Bujtas.
+
+        Previously, single characters weren't shaped in the fast text codepath,
+        because shaping in the fast text codepath was just for kerning and
+        ligatures. Kerning didn't need to shape individual characters because
+        kerning only applies to pairs of characters, and ligatures didn't need
+        to shape individual characters because two characters are required to
+        form a ligature. However, now that we want to replace the complex text
+        codepath with a new-and-improved fast text codepath, we have to perform
+        all shaping in the fast text codepath, regardless of how many characters
+        are present.
+
+        Test: fast/text/single-character-shaping.html
+
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::applyFontTransforms):
+        (WebCore::WidthIterator::commitCurrentFontRange):
+        (WebCore::WidthIterator::advanceInternal):
+        (WebCore::WidthIterator::shouldApplyFontTransforms const): Deleted.
+        * platform/graphics/WidthIterator.h:
+        * platform/graphics/coretext/FontCoreText.cpp:
+        (WebCore::Font::applyTransforms): Keep kerning disabled for single glyphs,
+        because of performance. This will be able to be removed when rdar://82195405
+        is fixed.
+        * rendering/mathml/RenderMathMLOperator.cpp:
+        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths):
+
 2021-08-21  Alan Bujtas  <za...@apple.com>
 
         [IFC][Integration] Add painting support for vertical text content

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (281377 => 281378)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-21 19:18:51 UTC (rev 281378)
@@ -80,22 +80,11 @@
     return codepoint >= 0xE001 && codepoint <= 0xE537;
 }
 
-inline auto WidthIterator::shouldApplyFontTransforms(const GlyphBuffer& glyphBuffer, unsigned lastGlyphCount, unsigned currentCharacterIndex) const -> TransformsType
+inline auto WidthIterator::applyFontTransforms(GlyphBuffer& glyphBuffer, unsigned lastGlyphCount, const Font& font, CharactersTreatedAsSpace& charactersTreatedAsSpace) -> ApplyFontTransformsResult
 {
-    ASSERT(currentCharacterIndex <= m_run.length());
-    if (glyphBuffer.size() == (lastGlyphCount + 1) && currentCharacterIndex && isSoftBankEmoji(m_run.text()[currentCharacterIndex - 1]))
-        return TransformsType::Forced;
-    if (m_run.length() <= 1)
-        return TransformsType::None;
-    return TransformsType::NotForced;
-}
-
-inline auto WidthIterator::applyFontTransforms(GlyphBuffer& glyphBuffer, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font& font, bool force, CharactersTreatedAsSpace& charactersTreatedAsSpace) -> ApplyFontTransformsResult
-{
-    ASSERT_UNUSED(currentCharacterIndex, shouldApplyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex) != WidthIterator::TransformsType::None);
-
     auto glyphBufferSize = glyphBuffer.size();
-    if (!force && glyphBufferSize <= lastGlyphCount + 1)
+    ASSERT(lastGlyphCount <= glyphBufferSize);
+    if (lastGlyphCount >= glyphBufferSize)
         return { 0, makeGlyphBufferAdvance() };
 
     GlyphBufferAdvance* advances = glyphBuffer.advances(0);
@@ -103,8 +92,6 @@
     for (unsigned i = lastGlyphCount; i < glyphBufferSize; ++i)
         beforeWidth += width(advances[i]);
 
-    ASSERT(lastGlyphCount <= glyphBufferSize);
-
     auto initialAdvance = font.applyTransforms(glyphBuffer, lastGlyphCount, m_currentCharacterIndex, m_enableKerning, m_requiresShaping, m_font.fontDescription().computedLocale(), m_run.text(), m_run.direction());
 
 #if USE(CTFONTSHAPEGLYPHS_WORKAROUND)
@@ -192,7 +179,7 @@
     setHeight(advanceToExpand, height(advanceToExpand) + height(initialAdvance));
 }
 
-void WidthIterator::applyInitialAdvance(GlyphBuffer& glyphBuffer, std::optional<GlyphBufferAdvance> initialAdvance, unsigned lastGlyphCount)
+void WidthIterator::applyInitialAdvance(GlyphBuffer& glyphBuffer, GlyphBufferAdvance initialAdvance, unsigned lastGlyphCount)
 {
     ASSERT(glyphBuffer.size() >= lastGlyphCount);
 
@@ -208,17 +195,15 @@
         m_leftoverInitialAdvance = makeGlyphBufferAdvance();
     }
 
-    if (initialAdvance) {
-        if (m_run.direction() == TextDirection::RTL)
-            m_leftoverInitialAdvance = initialAdvance.value();
-        else {
-            if (lastGlyphCount) {
-                auto& visuallyPreviousAdvance = *glyphBuffer.advances(lastGlyphCount - 1);
-                expandWithInitialAdvance(visuallyPreviousAdvance, initialAdvance.value());
-                m_runWidthSoFar += width(initialAdvance.value());
-            } else
-                glyphBuffer.expandInitialAdvance(initialAdvance.value());
-        }
+    if (m_run.direction() == TextDirection::RTL)
+        m_leftoverInitialAdvance = initialAdvance;
+    else {
+        if (lastGlyphCount) {
+            auto& visuallyPreviousAdvance = *glyphBuffer.advances(lastGlyphCount - 1);
+            expandWithInitialAdvance(visuallyPreviousAdvance, initialAdvance);
+            m_runWidthSoFar += width(initialAdvance);
+        } else
+            glyphBuffer.expandInitialAdvance(initialAdvance);
     }
 }
 
@@ -230,14 +215,9 @@
         ASSERT(&glyphBuffer.fontAt(i) == font);
 #endif
 
-    std::optional<GlyphBufferAdvance> initialAdvance;
-    auto transformsType = shouldApplyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex);
-    if (transformsType != TransformsType::None) {
-        auto applyFontTransformsResult = applyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex, *font, transformsType == TransformsType::Forced, charactersTreatedAsSpace);
-        m_runWidthSoFar += applyFontTransformsResult.additionalAdvance;
-        initialAdvance = applyFontTransformsResult.initialAdvance;
-    }
-    applyInitialAdvance(glyphBuffer, initialAdvance, lastGlyphCount);
+    auto applyFontTransformsResult = applyFontTransforms(glyphBuffer, lastGlyphCount, *font, charactersTreatedAsSpace);
+    m_runWidthSoFar += applyFontTransformsResult.additionalAdvance;
+    applyInitialAdvance(glyphBuffer, applyFontTransformsResult.initialAdvance, lastGlyphCount);
     m_currentCharacterIndex = currentCharacterIndex;
 
     if (widthOfCurrentFontRange && m_fallbackFonts && font != &primaryFont) {
@@ -335,8 +315,7 @@
         else
             widthOfCurrentFontRange += width;
 
-        auto transformsType = shouldApplyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex);
-        if (transformsType != TransformsType::None && FontCascade::treatAsSpace(character)) {
+        if (FontCascade::treatAsSpace(character)) {
             charactersTreatedAsSpace.constructAndAppend(
                 currentCharacterIndex,
                 character == ' ',

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.h (281377 => 281378)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-21 19:18:51 UTC (rev 281378)
@@ -67,9 +67,9 @@
         float additionalAdvance;
         GlyphBufferAdvance initialAdvance;
     };
-    ApplyFontTransformsResult applyFontTransforms(GlyphBuffer&, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font&, bool force, CharactersTreatedAsSpace&);
+    ApplyFontTransformsResult applyFontTransforms(GlyphBuffer&, unsigned lastGlyphCount, const Font&, CharactersTreatedAsSpace&);
     void commitCurrentFontRange(GlyphBuffer&, unsigned& lastGlyphCount, unsigned currentCharacterIndex, const Font*&, const Font& newFont, const Font& primaryFont, UChar32 character, float& widthOfCurrentFontRange, float nextCharacterWidth, CharactersTreatedAsSpace&);
-    void applyInitialAdvance(GlyphBuffer&, std::optional<GlyphBufferAdvance> initialAdvance, unsigned lastGlyphCount);
+    void applyInitialAdvance(GlyphBuffer&, GlyphBufferAdvance initialAdvance, unsigned lastGlyphCount);
 
     bool hasExtraSpacing() const;
     void applyExtraSpacingAfterShaping(GlyphBuffer&, unsigned characterStartIndex, unsigned glyphBufferStartIndex, unsigned characterDestinationIndex, float startingRunWidth);

Modified: trunk/Source/WebCore/platform/graphics/coretext/FontCoreText.cpp (281377 => 281378)


--- trunk/Source/WebCore/platform/graphics/coretext/FontCoreText.cpp	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Source/WebCore/platform/graphics/coretext/FontCoreText.cpp	2021-08-21 19:18:51 UTC (rev 281378)
@@ -608,15 +608,15 @@
     auto substring = text.substring(beginningStringIndex);
     auto upconvertedCharacters = substring.upconvertedCharacters();
     auto localeString = LocaleCocoa::canonicalLanguageIdentifierFromString(locale).string().createCFString();
+    auto numberOfInputGlyphs = glyphBuffer.size() - beginningGlyphIndex;
+    // FIXME: Enable kerning for single glyphs when rdar://82195405 is fixed
     CTFontShapeOptions options = kCTFontShapeWithClusterComposition
-        | (enableKerning ? kCTFontShapeWithKerning : 0)
+        | (enableKerning && numberOfInputGlyphs ? kCTFontShapeWithKerning : 0)
         | (textDirection == TextDirection::RTL ? kCTFontShapeRightToLeft : 0);
 
     for (unsigned i = 0; i < glyphBuffer.size() - beginningGlyphIndex; ++i)
         glyphBuffer.offsetsInString(beginningGlyphIndex)[i] -= beginningStringIndex;
 
-    auto numberOfInputGlyphs = glyphBuffer.size() - beginningGlyphIndex;
-
     auto initialAdvance = CTFontShapeGlyphs(
         m_platformData.ctFont(),
         glyphBuffer.glyphs(beginningGlyphIndex),

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp (281377 => 281378)


--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp	2021-08-21 19:18:51 UTC (rev 281378)
@@ -199,8 +199,7 @@
             // In some fonts, glyphs for invisible operators have nonzero width. Consequently, we subtract that width here to avoid wide gaps.
             GlyphData data = "" false);
             float glyphWidth = data.font ? data.font->widthForGlyph(data.glyph) : 0;
-            ASSERT(glyphWidth <= preferredWidth);
-            preferredWidth -= glyphWidth;
+            preferredWidth -= std::min(LayoutUnit(glyphWidth), preferredWidth);
         }
     } else
         preferredWidth = m_mathOperator.maxPreferredWidth();

Modified: trunk/Tools/ChangeLog (281377 => 281378)


--- trunk/Tools/ChangeLog	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Tools/ChangeLog	2021-08-21 19:18:51 UTC (rev 281378)
@@ -1,3 +1,14 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Single characters don't get shaped in the fast text codepath
+        https://bugs.webkit.org/show_bug.cgi?id=186804
+
+        Reviewed by Alan Bujtas.
+
+        Huge thanks to Laurence Penney to contributing this test font!!!
+
+        * Scripts/webkitpy/common/config/contributors.json:
+
 2021-08-21  Daniel Kolesa  <dkol...@igalia.com>
 
         [GLIB] Do not assume log success in apply-build-revision-to-files

Modified: trunk/Tools/Scripts/webkitpy/common/config/contributors.json (281377 => 281378)


--- trunk/Tools/Scripts/webkitpy/common/config/contributors.json	2021-08-21 18:19:40 UTC (rev 281377)
+++ trunk/Tools/Scripts/webkitpy/common/config/contributors.json	2021-08-21 19:18:51 UTC (rev 281378)
@@ -3752,6 +3752,11 @@
          "lvidacs"
       ]
    },
+   "Laurence Penney" : {
+      "emails" : [
+         "l...@lorp.org"
+      ]
+   },
    "Lauro Moura" : {
       "emails" : [
          "lmo...@igalia.com",
@@ -6211,4 +6216,4 @@
       ],
       "status" : "reviewer"
    }
-}
+}
\ No newline at end of file
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to