Title: [281294] trunk/Source/WebCore
Revision
281294
Author
[email protected]
Date
2021-08-19 21:53:20 -0700 (Thu, 19 Aug 2021)

Log Message

The fast text codepath does not handle run initial advances
https://bugs.webkit.org/show_bug.cgi?id=227979

Reviewed by Alan Bujtas.

This is the next step to delete the complex text codepath from Cocoa ports.

The initial advance contributes to the layout width of text. Its purpose is to move
all the visually successive glyphs to the right. For the leftmost run, WidthIterator
saves this initial advance to the GlyphBuffer, because knowing it is necessary to
compute the paint location of glyphs (inside GlyphBuffer::flatten()). For all other
runs other than the leftmost run, those runs' initial advance is added to the advance
width of whichever glyph ends up being just to the left of the run. In LTR, this is
the last glyph of the last (logical) run, whereas in RTL this is the first glyph of
the next (logical) run.

Because this is just adding infrastructure, it doesn't add any tests yet. This will be
tested when we delete the complex text codepath.

* platform/graphics/ComplexTextController.h: Because we're going to stop using
ComplexTextController, we should move this (presumably helpful) comment somewhere
where it will be accessible to the Cocoa ports. This would be GlyphBuffer::flatten().
* platform/graphics/Font.cpp:
(WebCore::Font::applyTransforms const): Return the initial advance.
* platform/graphics/Font.h: Ditto.
* platform/graphics/FontCascade.cpp:
(WebCore::FontCascade::widthOfTextRange const):
(WebCore::FontCascade::widthForSimpleText const): Make sure that the initial advance
contributes to layout width.
(WebCore::FontCascade::layoutSimpleText const): The initial advance is actually NOT
supposed to point directly to the first glyph's paint position. See
https://bugs.webkit.org/show_bug.cgi?id=228180.
(WebCore::FontCascade::drawEmphasisMarks const):
* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBuffer::flatten):
(WebCore::GlyphBuffer::isFlattened const):
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::applyFontTransforms): Return the initial advance.
(WebCore::expandWithInitialAdvance):
(WebCore::WidthIterator::applyInitialAdvance): This implements the logic above, where
the initial advance of non-leftmost runs get added to the visually previous glyph's
advance. For LTR, we can just add it directly to the previously-recorded glyph advance.
However, for RTL, we have to save the initial advance to a variable, which is named
m_leftoverInitialAdvance, and apply it when we encounter the next run. This is because
WidthIterator encounters run in logical order.
(WebCore::WidthIterator::commitCurrentFontRange):
(WebCore::WidthIterator::finalize): For RTL, if the last run has an initial advance,
we need to save it to the GlyphBuffer's initial advance field. We know if the last run
has an initial advance because there will still be data in m_leftoverInitialAdvance
left over.
* platform/graphics/WidthIterator.h:
* platform/graphics/coretext/FontCoreText.cpp:
(WebCore::Font::applyTransforms const): Return the initial advance.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (281293 => 281294)


--- trunk/Source/WebCore/ChangeLog	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/ChangeLog	2021-08-20 04:53:20 UTC (rev 281294)
@@ -1,5 +1,61 @@
 2021-08-19  Myles C. Maxfield  <[email protected]>
 
+        The fast text codepath does not handle run initial advances
+        https://bugs.webkit.org/show_bug.cgi?id=227979
+
+        Reviewed by Alan Bujtas.
+
+        This is the next step to delete the complex text codepath from Cocoa ports.
+
+        The initial advance contributes to the layout width of text. Its purpose is to move
+        all the visually successive glyphs to the right. For the leftmost run, WidthIterator
+        saves this initial advance to the GlyphBuffer, because knowing it is necessary to
+        compute the paint location of glyphs (inside GlyphBuffer::flatten()). For all other
+        runs other than the leftmost run, those runs' initial advance is added to the advance
+        width of whichever glyph ends up being just to the left of the run. In LTR, this is
+        the last glyph of the last (logical) run, whereas in RTL this is the first glyph of
+        the next (logical) run.
+
+        Because this is just adding infrastructure, it doesn't add any tests yet. This will be
+        tested when we delete the complex text codepath.
+
+        * platform/graphics/ComplexTextController.h: Because we're going to stop using
+        ComplexTextController, we should move this (presumably helpful) comment somewhere
+        where it will be accessible to the Cocoa ports. This would be GlyphBuffer::flatten().
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::applyTransforms const): Return the initial advance.
+        * platform/graphics/Font.h: Ditto.
+        * platform/graphics/FontCascade.cpp:
+        (WebCore::FontCascade::widthOfTextRange const):
+        (WebCore::FontCascade::widthForSimpleText const): Make sure that the initial advance
+        contributes to layout width.
+        (WebCore::FontCascade::layoutSimpleText const): The initial advance is actually NOT
+        supposed to point directly to the first glyph's paint position. See
+        https://bugs.webkit.org/show_bug.cgi?id=228180.
+        (WebCore::FontCascade::drawEmphasisMarks const):
+        * platform/graphics/GlyphBuffer.h:
+        (WebCore::GlyphBuffer::flatten):
+        (WebCore::GlyphBuffer::isFlattened const):
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::applyFontTransforms): Return the initial advance.
+        (WebCore::expandWithInitialAdvance):
+        (WebCore::WidthIterator::applyInitialAdvance): This implements the logic above, where
+        the initial advance of non-leftmost runs get added to the visually previous glyph's
+        advance. For LTR, we can just add it directly to the previously-recorded glyph advance.
+        However, for RTL, we have to save the initial advance to a variable, which is named
+        m_leftoverInitialAdvance, and apply it when we encounter the next run. This is because
+        WidthIterator encounters run in logical order.
+        (WebCore::WidthIterator::commitCurrentFontRange):
+        (WebCore::WidthIterator::finalize): For RTL, if the last run has an initial advance,
+        we need to save it to the GlyphBuffer's initial advance field. We know if the last run
+        has an initial advance because there will still be data in m_leftoverInitialAdvance
+        left over.
+        * platform/graphics/WidthIterator.h:
+        * platform/graphics/coretext/FontCoreText.cpp:
+        (WebCore::Font::applyTransforms const): Return the initial advance.
+
+2021-08-19  Myles C. Maxfield  <[email protected]>
+
         [Cocoa] Stop honoring any dot-prefixed font names
         https://bugs.webkit.org/show_bug.cgi?id=228177
 

Modified: trunk/Source/WebCore/platform/graphics/ComplexTextController.h (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/ComplexTextController.h	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/ComplexTextController.h	2021-08-20 04:53:20 UTC (rev 281294)
@@ -105,33 +105,6 @@
         unsigned endOffsetAt(unsigned i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; }
         const CGGlyph* glyphs() const { return m_glyphs.data(); }
 
-        /*
-         * This is the format of the information CoreText gives us about each run:
-         *
-         *                                        ----->X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
-         *                                       /     7                          7                          7
-         *                                      /     /                          /                          /
-         *                   (Initial advance) /     / (Glyph origin)           / (Glyph origin)           / (Glyph origin)
-         *                  -------------------     /                          /                          /
-         *                 /                       /                          /                          /
-         *                X                       X--------------------------X--------------------------X--------------------------X
-         * (text position ^)                             (base advance)             (base advance)             (base advance)
-         *
-         *
-         *
-         *
-         *
-         * And here is the output we transform this into (for each run):
-         *
-         *                                        ----->X------------------------->X------------------------->X
-         *                                       /            (Paint advance)            (Paint advance)       \
-         *                                      /                                                               \
-         *                   (Initial advance) /                                                                 \ (Paint advance)
-         *                  -------------------                                                                   ----------------
-         *                 /                                                                                                      \
-         *                X--------------------------------------------------X--------------------------X--------------------------X
-         * (text position ^)                (layout advance)                       (layout advance)           (layout advance)
-         */
         void growInitialAdvanceHorizontally(float delta) { m_initialAdvance.expand(delta, 0); }
         FloatSize initialAdvance() const { return m_initialAdvance; }
         const FloatSize* baseAdvances() const { return m_baseAdvances.data(); }

Modified: trunk/Source/WebCore/platform/graphics/Font.cpp (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/Font.cpp	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/Font.cpp	2021-08-20 04:53:20 UTC (rev 281294)
@@ -542,8 +542,9 @@
 }
 
 #if !USE(CORE_TEXT)
-void Font::applyTransforms(GlyphBuffer&, unsigned, unsigned, bool, bool, const AtomString&, StringView, TextDirection) const
+GlyphBufferAdvance Font::applyTransforms(GlyphBuffer&, unsigned, unsigned, bool, bool, const AtomString&, StringView, TextDirection) const
 {
+    return makeGlyphBufferAdvance();
 }
 #endif
 

Modified: trunk/Source/WebCore/platform/graphics/Font.h (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/Font.h	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/Font.h	2021-08-20 04:53:20 UTC (rev 281294)
@@ -206,7 +206,7 @@
 #endif
 
     bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
-    void applyTransforms(GlyphBuffer&, unsigned beginningGlyphIndex, unsigned beginningStringIndex, bool enableKerning, bool requiresShaping, const AtomString& locale, StringView text, TextDirection) const;
+    GlyphBufferAdvance applyTransforms(GlyphBuffer&, unsigned beginningGlyphIndex, unsigned beginningStringIndex, bool enableKerning, bool requiresShaping, const AtomString& locale, StringView text, TextDirection) const;
 
     // Returns nullopt if none of the glyphs are OT-SVG glyphs.
     std::optional<BitVector> findOTSVGGlyphs(const GlyphBufferGlyph*, unsigned count) const;

Modified: trunk/Source/WebCore/platform/graphics/FontCascade.cpp (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/FontCascade.cpp	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.cpp	2021-08-20 04:53:20 UTC (rev 281294)
@@ -254,6 +254,8 @@
         simpleIterator.advance(run.length(), glyphBuffer);
         totalWidth = simpleIterator.runWidthSoFar();
         simpleIterator.finalize(glyphBuffer);
+        // FIXME: Finalizing the WidthIterator can affect the total width.
+        // We might need to adjust the various widths we've measured to account for that.
     }
 
     if (outWidthBeforeRange)
@@ -319,7 +321,7 @@
         glyphBuffer.add(glyph, font, glyphWidth, i);
     }
 
-    font.applyTransforms(glyphBuffer, 0, 0, enableKerning(), requiresShaping(), fontDescription().computedLocale(), text, textDirection);
+    auto initialAdvance = font.applyTransforms(glyphBuffer, 0, 0, enableKerning(), requiresShaping(), fontDescription().computedLocale(), text, textDirection);
     // This is needed only to match the result of the slow path.
     // Same glyph widths but different floating point arithmetic can produce different run width.
     float runWidthDifferenceWithTransformApplied = -runWidth;
@@ -327,6 +329,8 @@
         runWidthDifferenceWithTransformApplied += WebCore::width(glyphBuffer.advanceAt(i));
     runWidth += runWidthDifferenceWithTransformApplied;
 
+    runWidth += WebCore::width(initialAdvance);
+
     if (cacheEntry)
         *cacheEntry = runWidth;
     return runWidth;
@@ -1270,11 +1274,6 @@
         initialAdvance = beforeWidth;
     }
     glyphBuffer.expandInitialAdvance(initialAdvance);
-    if (!glyphBuffer.isEmpty()) {
-        // The initial advance is supposed to point directly to the first glyph's paint position.
-        // See the ascii-art diagram in ComplexTextController.h.
-        glyphBuffer.expandInitialAdvance(makeGlyphBufferAdvance(x(glyphBuffer.originAt(0)), y(glyphBuffer.originAt(0))));
-    }
 
     // The glyph buffer is currently in logical order,
     // but we need to return the results in visual order.
@@ -1326,6 +1325,7 @@
     return !font.isInterstitial() || font.visibility() == Font::Visibility::Visible || customFontNotReadyAction == FontCascade::CustomFontNotReadyAction::UseFallbackIfFontNotReady;
 }
 
+// This function assumes the GlyphBuffer's initial advance has already been incorporated into the start point.
 void FontCascade::drawGlyphBuffer(GraphicsContext& context, const GlyphBuffer& glyphBuffer, FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
 {
     ASSERT(glyphBuffer.isFlattened());
@@ -1387,6 +1387,9 @@
     Glyph markGlyph = markGlyphData.value().glyph;
     Glyph spaceGlyph = markFontData->spaceGlyph();
 
+    // FIXME: This needs to take the initial advance into account.
+    // The problem might actually be harder for complex text, though.
+    // Putting a mark over every glyph probably isn't great in complex scripts.
     float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(*markFontData, markGlyph), point.y());
 

Modified: trunk/Source/WebCore/platform/graphics/GlyphBuffer.h (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-08-20 04:53:20 UTC (rev 281294)
@@ -165,31 +165,61 @@
         m_offsetsInString.shrink(truncationPoint);
     }
 
-    // FontCascade::layoutText() returns a GlyphBuffer which includes layout information that is split
-    // into "advances" and "origins". See the ASCII-art diagram in ComplexTextController.h
-    // In order to get paint advances, we need to run this "flatten" operation.
-    // This merges the layout advances and origins together,
-    // leaves the paint advances in the "m_advances" field,
-    // and zeros-out the origins in the "m_origins" field.
+    /*
+     * This is the unflattened format:
+     *
+     *                                              X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
+     *                                             7                          7                          7
+     *                                            /                          /                          /
+     *                                           / (Origin)                 / (Origin)                 / (Origin)
+     *                                          /                          /                          /
+     *                                         /                          /                          /
+     *                X---------------------->X------------------------->X------------------------->X------------------------->X
+     * (text position ^)  (Initial advance)            (Advance)                  (Advance)                   (Advance)
+     *
+     *
+     *
+     *
+     *
+     * And this is what we transform it into:
+     *
+     *                                        ----->X------------------------->X------------------------->X
+     *                                       /               (Advance)                   (Advance)         \
+     *                                      /                                                               \
+     *                   (Initial advance) /                                                                 \   (Advance)
+     *                  -------------------                                                                   ----------------
+     *                 /                                                                                                      \
+     *                X                                                                                                        X
+     * (text position ^)
+     *
+     * This is an operation that discards all layout information, and preserves only paint information.
+     */
     void flatten()
     {
+        ASSERT(size() || (!width(m_initialAdvance) && !height(m_initialAdvance)));
+        if (size()) {
+            m_initialAdvance = makeGlyphBufferAdvance(
+                width(m_initialAdvance) + x(m_origins[0]),
+                height(m_initialAdvance) + y(m_origins[0]));
+        }
         for (unsigned i = 0; i < size(); ++i) {
             m_advances[i] = makeGlyphBufferAdvance(
                 -x(m_origins[i]) + width(m_advances[i]) + (i + 1 < size() ? x(m_origins[i + 1]) : 0),
-                -y(m_origins[i]) + height(m_advances[i]) + (i + 1 < size() ? y(m_origins[i + 1]) : 0)
-            );
+                -y(m_origins[i]) + height(m_advances[i]) + (i + 1 < size() ? y(m_origins[i + 1]) : 0));
             m_origins[i] = makeGlyphBufferOrigin();
         }
     }
 
+#if ASSERT_ENABLED
     bool isFlattened() const
     {
         for (unsigned i = 0; i < size(); ++i) {
-            if (m_origins[i] != makeGlyphBufferOrigin())
+            if (x(m_origins[i]) || y(m_origins[i]))
                 return false;
         }
         return true;
     }
+#endif
 
 private:
     void swap(unsigned index1, unsigned index2)

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-20 04:53:20 UTC (rev 281294)
@@ -90,13 +90,13 @@
     return TransformsType::NotForced;
 }
 
-inline float WidthIterator::applyFontTransforms(GlyphBuffer& glyphBuffer, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font& font, bool force, CharactersTreatedAsSpace& charactersTreatedAsSpace)
+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)
-        return 0;
+        return { 0, makeGlyphBufferAdvance() };
 
     GlyphBufferAdvance* advances = glyphBuffer.advances(0);
     float beforeWidth = 0;
@@ -105,7 +105,7 @@
 
     ASSERT(lastGlyphCount <= glyphBufferSize);
 
-    font.applyTransforms(glyphBuffer, lastGlyphCount, m_currentCharacterIndex, m_enableKerning, m_requiresShaping, m_font.fontDescription().computedLocale(), m_run.text(), m_run.direction());
+    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)
     // <rdar://problem/80798113>: If a character is not in BMP, and we don't have a glyph for it,
@@ -154,7 +154,7 @@
     for (unsigned i = lastGlyphCount; i < glyphBufferSize; ++i)
         afterWidth += width(advances[i]);
 
-    return afterWidth - beforeWidth;
+    return { afterWidth - beforeWidth, initialAdvance };
 }
 
 static inline std::pair<bool, bool> expansionLocation(bool ideograph, bool treatAsSpace, bool ltr, bool isAfterExpansion, bool forbidLeftExpansion, bool forbidRightExpansion, bool forceLeftExpansion, bool forceRightExpansion)
@@ -186,11 +186,52 @@
     return std::make_pair(expandLeft, expandRight);
 }
 
+static void expandWithInitialAdvance(GlyphBufferAdvance& advanceToExpand, const GlyphBufferAdvance& initialAdvance)
+{
+    setWidth(advanceToExpand, width(advanceToExpand) + width(initialAdvance));
+    setHeight(advanceToExpand, height(advanceToExpand) + height(initialAdvance));
+}
+
+void WidthIterator::applyInitialAdvance(GlyphBuffer& glyphBuffer, std::optional<GlyphBufferAdvance> initialAdvance, unsigned lastGlyphCount)
+{
+    ASSERT(glyphBuffer.size() >= lastGlyphCount);
+
+    if (glyphBuffer.size() <= lastGlyphCount)
+        return;
+
+    ASSERT(lastGlyphCount || (!width(m_leftoverInitialAdvance) && !height(m_leftoverInitialAdvance)));
+
+    if (m_run.direction() == TextDirection::RTL && lastGlyphCount) {
+        auto& visuallyLastAdvance = *glyphBuffer.advances(lastGlyphCount);
+        expandWithInitialAdvance(visuallyLastAdvance, m_leftoverInitialAdvance);
+        m_runWidthSoFar += width(m_leftoverInitialAdvance);
+        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());
+        }
+    }
+}
+
 void WidthIterator::commitCurrentFontRange(GlyphBuffer& glyphBuffer, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font& font, const Font& primaryFont, UChar32 character, float widthOfCurrentFontRange, CharactersTreatedAsSpace& charactersTreatedAsSpace)
 {
+    std::optional<GlyphBufferAdvance> initialAdvance;
     auto transformsType = shouldApplyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex);
-    if (transformsType != TransformsType::None)
-        m_runWidthSoFar += applyFontTransforms(glyphBuffer, lastGlyphCount, currentCharacterIndex, font, transformsType == TransformsType::Forced, charactersTreatedAsSpace);
+    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);
     m_currentCharacterIndex = currentCharacterIndex;
 
     if (widthOfCurrentFontRange && m_fallbackFonts && &font != &primaryFont) {
@@ -479,7 +520,9 @@
 void WidthIterator::finalize(GlyphBuffer& buffer)
 {
     ASSERT(m_run.rtl() || !m_leftoverJustificationWidth);
-    // In LTR this does nothing. In RTL, this adds left width by moving the whole run to the right.
+    // In LTR these do nothing. In RTL, these add left width by moving the whole run to the right.
+    buffer.expandInitialAdvance(m_leftoverInitialAdvance);
+    m_runWidthSoFar += width(m_leftoverInitialAdvance);
     buffer.expandInitialAdvance(m_leftoverJustificationWidth);
     m_runWidthSoFar += m_leftoverJustificationWidth;
     m_leftoverJustificationWidth = 0;

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.h (281293 => 281294)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-20 04:53:20 UTC (rev 281294)
@@ -63,8 +63,13 @@
 
     enum class TransformsType { None, Forced, NotForced };
     TransformsType shouldApplyFontTransforms(const GlyphBuffer&, unsigned lastGlyphCount, unsigned currentCharacterIndex) const;
-    float applyFontTransforms(GlyphBuffer&, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font&, bool force, CharactersTreatedAsSpace&);
+    struct ApplyFontTransformsResult {
+        float additionalAdvance;
+        GlyphBufferAdvance initialAdvance;
+    };
+    ApplyFontTransformsResult applyFontTransforms(GlyphBuffer&, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font&, bool force, CharactersTreatedAsSpace&);
     void commitCurrentFontRange(GlyphBuffer&, unsigned lastGlyphCount, unsigned currentCharacterIndex, const Font&, const Font& primaryFont, UChar32 character, float widthOfCurrentFontRange, CharactersTreatedAsSpace&);
+    void applyInitialAdvance(GlyphBuffer&, std::optional<GlyphBufferAdvance> initialAdvance, unsigned lastGlyphCount);
 
     bool hasExtraSpacing() const;
     void applyExtraSpacingAfterShaping(GlyphBuffer&, unsigned characterStartIndex, unsigned glyphBufferStartIndex, unsigned characterDestinationIndex, float startingRunWidth);
@@ -82,6 +87,7 @@
     HashSet<const Font*>* m_fallbackFonts { nullptr };
 
     std::optional<unsigned> m_lastCharacterIndex;
+    GlyphBufferAdvance m_leftoverInitialAdvance { makeGlyphBufferAdvance() };
     unsigned m_currentCharacterIndex { 0 };
     float m_leftoverJustificationWidth { 0 };
     float m_runWidthSoFar { 0 };

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


--- trunk/Source/WebCore/platform/graphics/coretext/FontCoreText.cpp	2021-08-20 04:07:08 UTC (rev 281293)
+++ trunk/Source/WebCore/platform/graphics/coretext/FontCoreText.cpp	2021-08-20 04:53:20 UTC (rev 281294)
@@ -584,11 +584,10 @@
 
 #endif
 
-void Font::applyTransforms(GlyphBuffer& glyphBuffer, unsigned beginningGlyphIndex, unsigned beginningStringIndex, bool enableKerning, bool requiresShaping, const AtomString& locale, StringView text, TextDirection textDirection) const
+GlyphBufferAdvance Font::applyTransforms(GlyphBuffer& glyphBuffer, unsigned beginningGlyphIndex, unsigned beginningStringIndex, bool enableKerning, bool requiresShaping, const AtomString& locale, StringView text, TextDirection textDirection) const
 {
     UNUSED_PARAM(requiresShaping);
 
-    // FIXME: Implement GlyphBuffer initial advance.
 #if USE(CTFONTSHAPEGLYPHS)
     auto handler = ^(CFRange range, CGGlyph** newGlyphsPointer, CGSize** newAdvancesPointer, CGPoint** newOffsetsPointer, CFIndex** newIndicesPointer)
     {
@@ -616,18 +615,23 @@
     for (unsigned i = 0; i < glyphBuffer.size() - beginningGlyphIndex; ++i)
         glyphBuffer.offsetsInString(beginningGlyphIndex)[i] -= beginningStringIndex;
 
-    CTFontShapeGlyphs(
+    auto numberOfInputGlyphs = glyphBuffer.size() - beginningGlyphIndex;
+
+    auto initialAdvance = CTFontShapeGlyphs(
         m_platformData.ctFont(),
         glyphBuffer.glyphs(beginningGlyphIndex),
-        reinterpret_cast<CGSize*>(glyphBuffer.advances(beginningGlyphIndex)),
-        reinterpret_cast<CGPoint*>(glyphBuffer.origins(beginningGlyphIndex)),
+        glyphBuffer.advances(beginningGlyphIndex),
+        glyphBuffer.origins(beginningGlyphIndex),
         glyphBuffer.offsetsInString(beginningGlyphIndex),
         reinterpret_cast<const UniChar*>(upconvertedCharacters.get()),
-        glyphBuffer.size() - beginningGlyphIndex,
+        numberOfInputGlyphs,
         options,
         localeString.get(),
         handler);
 
+    ASSERT(numberOfInputGlyphs || glyphBuffer.size() == beginningGlyphIndex);
+    ASSERT(numberOfInputGlyphs || (!initialAdvance.width && !initialAdvance.height));
+
     for (unsigned i = 0; i < glyphBuffer.size() - beginningGlyphIndex; ++i)
         glyphBuffer.offsetsInString(beginningGlyphIndex)[i] += beginningStringIndex;
 
@@ -652,11 +656,15 @@
 
     CTFontTransformOptions options = (enableKerning ? kCTFontTransformApplyPositioning : 0) | kCTFontTransformApplyShaping;
     CTFontTransformGlyphs(m_platformData.ctFont(), glyphBuffer.glyphs(beginningGlyphIndex), reinterpret_cast<CGSize*>(glyphBuffer.advances(beginningGlyphIndex)), glyphBuffer.size() - beginningGlyphIndex, options);
+
+    auto initialAdvance = makeGlyphBufferAdvance();
 #endif
 
     // See the comment above in this function where the other call to reverse() is.
     if (textDirection == TextDirection::RTL)
         glyphBuffer.reverse(beginningGlyphIndex, glyphBuffer.size() - beginningGlyphIndex);
+
+    return initialAdvance;
 }
 
 static int extractNumber(CFNumberRef number)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to