Skip to content

Commit 9a0477f

Browse files
committed
text-autospace: implement ideograph-alpha for complex path within an text run
https://bugs.webkit.org/show_bug.cgi?id=277716 rdar://133309470 Reviewed by Matthieu Dubet. We are relanding this patch as its first version was reverted due to performance reasons. On the current iteration we are avoiding classifying characters when not needed (text-autospace: no-autospace). We also won't keep the parralel vector for the added spacing in such a case. Original patch description: This patch implements the processing of text-autospace: ideogram-alpha only within an element. We don't yet handle element boundaries here. Although we pass SpacingState context from one ComplexTextController to another, we do that here in a limited way, only for measuring text for layout and for painting. There are other places in code which this will be necessary, for example, for handling element boundaries. 1. During the construction of ComplexTextController, we call ::adjustGlyphsAndAdvances which already iterates through glyphs and adjust spacing for other reasons. Now we process each pair of characters related to these glyphs here, adding the spacing necessary before the "current" character. For that reason, the SpacingState stores information about the previous character of a run. We also save the measured spacing in a new parallel vector m_textAutoSpaceSpacings. At this phase we can only manipulate a glyph advance, however, for adding space "before" a glyph, we need to move the glyph to the logical right, which is done later on ::advance. 2. ComplexTextController::advance is called for both layout and painting, but during painting it has access to a GlyphBuffer and it add glyphs into it. We are introducing a new GlyphBuffer::add function that also takes the glyph's origin, so we can manipulate the origin as necessary by adding the previous calculated spacing. 3. Doing #1 and #2 is already enough for painting the extra spacing between relevant characters according to their classes. Howeverm the width measured during layout would be broken because IFC splits text content into inlineTextItem(s) and measure the width of each item independently. This means that we already have to handle SpacingState passing here, otherwise we are not able to handle spacing between characters on the boundary of different InlineTextItem. * Source/WTF/wtf/text/CharacterProperties.h: (WTF::isPunctuation): (WTF::isOpeningPunctuation): (WTF::isClosingPunctuation): (WTF::isOfScriptType): (WTF::eastAsianWidth): (WTF::isEastAsianFullWidth): (WTF::isCJKSymbolOrPunctuation): * Source/WebCore/Sources.txt: * Source/WebCore/WebCore.xcodeproj/project.pbxproj: * Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp: (WebCore::Layout::InlineItemsBuilder::computeInlineTextItemWidths): * Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp: (WebCore::Layout::TextUtil::width): * Source/WebCore/layout/formattingContexts/inline/text/TextUtil.h: (WebCore::Layout::TextUtil::width): * Source/WebCore/platform/graphics/ComplexTextController.cpp: (WebCore::ComplexTextController::ComplexTextController): (WebCore::ComplexTextController::advance): (WebCore::ComplexTextController::adjustGlyphsAndAdvances): (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): * Source/WebCore/platform/graphics/ComplexTextController.h: (WebCore::ComplexTextController::ComplexTextRun::textAutospaceSize const): * Source/WebCore/platform/graphics/FontCascade.cpp: (WebCore::FontCascade::width const): (WebCore::FontCascade::codePath const): * Source/WebCore/platform/graphics/GlyphBuffer.h: (WebCore::GlyphBuffer::add): * Source/WebCore/platform/graphics/TextRun.cpp: * Source/WebCore/platform/graphics/TextRun.h: * Source/WebCore/platform/graphics/WidthCache.h: (WebCore::WidthCache::add): (WebCore::WidthCache::invalidateCacheForTextSpacing): * Source/WebCore/platform/graphics/coretext/ComplexTextControllerCoreText.mm: (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): * Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp: (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): * Source/WebCore/platform/graphics/skia/ComplexTextControllerSkia.cpp: (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): * Source/WebCore/platform/text/TextSpacing.cpp: Added. (WebCore::TextAutospace::shouldApplySpacing const): (WebCore::TextAutospace::textAutospaceSize): (WebCore::TextSpacing::isIdeograph): (WebCore::TextSpacing::isNonIdeographicNumeral): (WebCore::TextSpacing::characterClass): * Source/WebCore/platform/text/TextSpacing.h: (WebCore::TextAutospace::hasIdeographAlpha const): (WebCore::TextAutospace::hasIdeographNumeric const): Canonical link: https://commits.webkit.org/282511@main
1 parent 24b5b08 commit 9a0477f

19 files changed

+289
-15
lines changed

Source/WTF/wtf/text/CharacterProperties.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#pragma once
2727

2828
#include <unicode/uchar.h>
29+
#include <unicode/uscript.h>
2930
#include <wtf/text/StringCommon.h>
3031

3132
namespace WTF {
@@ -113,6 +114,48 @@ inline bool isPrivateUseAreaCharacter(char32_t character)
113114
return block == UBLOCK_PRIVATE_USE_AREA || block == UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_A || block == UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B;
114115
}
115116

117+
inline bool isPunctuation(char32_t character)
118+
{
119+
return U_GET_GC_MASK(character) & U_GC_P_MASK;
120+
}
121+
122+
inline bool isOpeningPunctuation(uint32_t generalCategoryMask)
123+
{
124+
return generalCategoryMask & U_GC_PS_MASK;
125+
}
126+
127+
inline bool isClosingPunctuation(uint32_t generalCategoryMask)
128+
{
129+
return generalCategoryMask & U_GC_PE_MASK;
130+
}
131+
132+
inline bool isOfScriptType(char32_t codePoint, UScriptCode scriptType)
133+
{
134+
UErrorCode error = U_ZERO_ERROR;
135+
UScriptCode script = uscript_getScript(codePoint, &error);
136+
if (error != U_ZERO_ERROR) {
137+
LOG_ERROR("got ICU error while trying to look at scripts: %d", error);
138+
return false;
139+
}
140+
return script == scriptType;
141+
}
142+
143+
inline UEastAsianWidth eastAsianWidth(char32_t character)
144+
{
145+
return static_cast<UEastAsianWidth>(u_getIntPropertyValue(character, UCHAR_EAST_ASIAN_WIDTH));
146+
}
147+
148+
inline bool isEastAsianFullWidth(char32_t character)
149+
{
150+
return eastAsianWidth(character) == UEastAsianWidth::U_EA_FULLWIDTH;
151+
}
152+
153+
inline bool isCJKSymbolOrPunctuation(char32_t character)
154+
{
155+
// CJK Symbols and Punctuation block (U+3000–U+303F)
156+
return character >= 0x3000 && character <= 0x303F;
157+
}
158+
116159
} // namespace WTF
117160

118161
using WTF::isEmojiGroupCandidate;
@@ -125,3 +168,9 @@ using WTF::isEmojiModifierBase;
125168
using WTF::isDefaultIgnorableCodePoint;
126169
using WTF::isControlCharacter;
127170
using WTF::isPrivateUseAreaCharacter;
171+
using WTF::isPunctuation;
172+
using WTF::isOpeningPunctuation;
173+
using WTF::isClosingPunctuation;
174+
using WTF::isOfScriptType;
175+
using WTF::isEastAsianFullWidth;
176+
using WTF::isCJKSymbolOrPunctuation;

Source/WebCore/Sources.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2646,6 +2646,7 @@ platform/text/QuotedPrintable.cpp
26462646
platform/text/SegmentedString.cpp
26472647
platform/text/TextBoundaries.cpp
26482648
platform/text/TextFlags.cpp
2649+
platform/text/TextSpacing.cpp
26492650
platform/video-codecs/BitReader.cpp
26502651
platform/xr/openxr/OpenXRInput.cpp
26512652
platform/xr/openxr/OpenXRInputSource.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11158,6 +11158,7 @@
1115811158
4CA012DB29A7D56700C260C6 /* counterStyles.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = counterStyles.css; sourceTree = "<group>"; };
1115911159
4CB808832964AF4600BC59FE /* CSSCounterStyleDescriptors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSCounterStyleDescriptors.h; sourceTree = "<group>"; };
1116011160
4CB808842964AF4700BC59FE /* CSSCounterStyleDescriptors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCounterStyleDescriptors.cpp; sourceTree = "<group>"; };
11161+
4CBBE5192C5D41AF00B7786E /* TextSpacing.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TextSpacing.cpp; sourceTree = "<group>"; };
1116111162
4CBE86962955BA7F00832AAA /* CSSCounterStyleRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSCounterStyleRegistry.h; sourceTree = "<group>"; };
1116211163
4CBE86972955BA7F00832AAA /* CSSCounterStyleRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCounterStyleRegistry.cpp; sourceTree = "<group>"; };
1116311164
4CF2530E29C09454005CDDAA /* ListStyleType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ListStyleType.cpp; sourceTree = "<group>"; };
@@ -33247,6 +33248,7 @@
3324733248
BC4A533A256064E10028C592 /* TextDirection.h */,
3324833249
71D475A627D741FC00644599 /* TextFlags.cpp */,
3324933250
B2C3DA150D006C1D00EF6F26 /* TextFlags.h */,
33251+
4CBBE5192C5D41AF00B7786E /* TextSpacing.cpp */,
3325033252
4C05BADF297AD120004FE77D /* TextSpacing.h */,
3325133253
A863E2001343412000274926 /* UnicodeBidi.h */,
3325233254
14476AA715DC4BB100305DB2 /* WritingMode.h */,

Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "TextBreakingPositionCache.h"
3434
#include "TextUtil.h"
3535
#include "UnicodeBidi.h"
36+
#include "platform/text/TextSpacing.h"
3637
#include <wtf/Scope.h>
3738
#include <wtf/text/TextBreakIterator.h>
3839
#include <wtf/unicode/CharacterNames.h>
@@ -679,6 +680,7 @@ static inline bool canCacheMeasuredWidthOnInlineTextItem(const InlineTextBox& in
679680

680681
void InlineItemsBuilder::computeInlineTextItemWidths(InlineItemList& inlineItemList)
681682
{
683+
TextSpacing::SpacingState spacingState;
682684
for (auto& inlineItem : inlineItemList) {
683685
auto* inlineTextItem = dynamicDowncast<InlineTextItem>(inlineItem);
684686
if (!inlineTextItem)
@@ -690,7 +692,8 @@ void InlineItemsBuilder::computeInlineTextItemWidths(InlineItemList& inlineItemL
690692
auto needsMeasuring = length && !inlineTextItem->isZeroWidthSpaceSeparator();
691693
if (!needsMeasuring || !canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, inlineTextItem->isWhitespace()))
692694
continue;
693-
inlineTextItem->setWidth(TextUtil::width(*inlineTextItem, inlineTextItem->style().fontCascade(), start, start + length, { }));
695+
inlineTextItem->setWidth(TextUtil::width(*inlineTextItem, inlineTextItem->style().fontCascade(), start, start + length, { }, TextUtil::UseTrailingWhitespaceMeasuringOptimization::Yes, spacingState));
696+
spacingState.lastCharacterClassFromPreviousRun = inlineItem.style().textAutospace().isNoAutospace() ? TextSpacing::CharacterClass::Undefined : TextSpacing::characterClass(inlineTextBox.content().characterAt(start + length - 1));
694697
}
695698
}
696699

Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "RenderStyleInlines.h"
3838
#include "SurrogatePairAwareTextIterator.h"
3939
#include "TextRun.h"
40+
#include "TextSpacing.h"
4041
#include "WidthIterator.h"
4142
#include <unicode/ubidi.h>
4243
#include <wtf/text/TextBreakIterator.h>
@@ -51,7 +52,7 @@ static inline InlineLayoutUnit spaceWidth(const FontCascade& fontCascade, bool c
5152
return fontCascade.widthOfSpaceString();
5253
}
5354

54-
InlineLayoutUnit TextUtil::width(const InlineTextBox& inlineTextBox, const FontCascade& fontCascade, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization useTrailingWhitespaceMeasuringOptimization)
55+
InlineLayoutUnit TextUtil::width(const InlineTextBox& inlineTextBox, const FontCascade& fontCascade, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization useTrailingWhitespaceMeasuringOptimization, TextSpacing::SpacingState spacingState)
5556
{
5657
if (from == to)
5758
return 0;
@@ -82,6 +83,8 @@ InlineLayoutUnit TextUtil::width(const InlineTextBox& inlineTextBox, const FontC
8283
auto run = WebCore::TextRun { StringView(text).substring(from, to - from), contentLogicalLeft, { }, ExpansionBehavior::defaultBehavior(), directionalOverride ? style.direction() : TextDirection::LTR, directionalOverride };
8384
if (!style.collapseWhiteSpace() && style.tabSize())
8485
run.setTabSize(true, style.tabSize());
86+
// FIXME: consider moving this to TextRun ctor
87+
run.setTextSpacingState(spacingState);
8588
width = fontCascade.width(run);
8689
}
8790

@@ -98,7 +101,7 @@ InlineLayoutUnit TextUtil::width(const InlineTextItem& inlineTextItem, const Fon
98101
return TextUtil::width(inlineTextItem, fontCascade, inlineTextItem.start(), inlineTextItem.end(), contentLogicalLeft);
99102
}
100103

101-
InlineLayoutUnit TextUtil::width(const InlineTextItem& inlineTextItem, const FontCascade& fontCascade, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization useTrailingWhitespaceMeasuringOptimization)
104+
InlineLayoutUnit TextUtil::width(const InlineTextItem& inlineTextItem, const FontCascade& fontCascade, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization useTrailingWhitespaceMeasuringOptimization, TextSpacing::SpacingState spacingState)
102105
{
103106
RELEASE_ASSERT(from >= inlineTextItem.start());
104107
RELEASE_ASSERT(to <= inlineTextItem.end());
@@ -116,7 +119,7 @@ InlineLayoutUnit TextUtil::width(const InlineTextItem& inlineTextItem, const Fon
116119
return std::max(0.f, width);
117120
}
118121
}
119-
return width(inlineTextItem.inlineTextBox(), fontCascade, from, to, contentLogicalLeft, useTrailingWhitespaceMeasuringOptimization);
122+
return width(inlineTextItem.inlineTextBox(), fontCascade, from, to, contentLogicalLeft, useTrailingWhitespaceMeasuringOptimization, spacingState);
120123
}
121124

122125
InlineLayoutUnit TextUtil::trailingWhitespaceWidth(const InlineTextBox& inlineTextBox, const FontCascade& fontCascade, size_t startPosition, size_t endPosition)

Source/WebCore/layout/formattingContexts/inline/text/TextUtil.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
namespace WebCore {
3737

38+
namespace TextSpacing {
39+
struct SpacingState;
40+
}
41+
3842
class RenderStyle;
3943
class TextRun;
4044

@@ -48,8 +52,8 @@ class TextUtil {
4852
public:
4953
enum class UseTrailingWhitespaceMeasuringOptimization : bool { No, Yes };
5054
static InlineLayoutUnit width(const InlineTextItem&, const FontCascade&, InlineLayoutUnit contentLogicalLeft);
51-
static InlineLayoutUnit width(const InlineTextItem&, const FontCascade&, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization = UseTrailingWhitespaceMeasuringOptimization::Yes);
52-
static InlineLayoutUnit width(const InlineTextBox&, const FontCascade&, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization = UseTrailingWhitespaceMeasuringOptimization::Yes);
55+
static InlineLayoutUnit width(const InlineTextItem&, const FontCascade&, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization = UseTrailingWhitespaceMeasuringOptimization::Yes, TextSpacing::SpacingState spacingState = { });
56+
static InlineLayoutUnit width(const InlineTextBox&, const FontCascade&, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft, UseTrailingWhitespaceMeasuringOptimization = UseTrailingWhitespaceMeasuringOptimization::Yes, TextSpacing::SpacingState spacingState = { });
5357

5458
static InlineLayoutUnit trailingWhitespaceWidth(const InlineTextBox&, const FontCascade&, size_t startPosition, size_t endPosition);
5559

Source/WebCore/platform/graphics/ComplexTextController.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ ComplexTextController::ComplexTextController(const FontCascade& font, const Text
124124
, m_expansion(run.expansion())
125125
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
126126
, m_forTextEmphasis(forTextEmphasis)
127+
, m_textSpacingState(run.textSpacingState())
127128
{
128129
computeExpansionOpportunity();
129130

@@ -554,7 +555,10 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
554555
return;
555556

556557
if (glyphBuffer && !m_characterInCurrentGlyph) {
558+
ASSERT(m_textAutoSpaceSpacings.isEmpty() || m_textAutoSpaceSpacings.size() == m_adjustedBaseAdvances.size());
559+
auto textAutoSpaceSpacing = m_textAutoSpaceSpacings.isEmpty() ? 0.0 : m_textAutoSpaceSpacings[glyphIndexIntoComplexTextController];
557560
auto currentGlyphOrigin = glyphOrigin(glyphIndexIntoComplexTextController);
561+
currentGlyphOrigin.move(textAutoSpaceSpacing, 0);
558562
GlyphBufferAdvance paintAdvance = makeGlyphBufferAdvance(adjustedBaseAdvance);
559563
if (!glyphIndexIntoCurrentRun) {
560564
// The first layout advance of every run includes the "initial layout advance." However, here, we need
@@ -572,7 +576,7 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
572576
setHeight(paintAdvance, height(paintAdvance) - glyphOrigin(glyphIndexIntoComplexTextController + 1).y() + m_complexTextRuns[currentRunIndex + 1]->initialAdvance().height());
573577
}
574578
setHeight(paintAdvance, -height(paintAdvance)); // Increasing y points down
575-
glyphBuffer->add(m_adjustedGlyphs[glyphIndexIntoComplexTextController], complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
579+
glyphBuffer->add(m_adjustedGlyphs[glyphIndexIntoComplexTextController], complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun), FloatPoint(textAutoSpaceSpacing, 0));
576580
}
577581

578582
unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
@@ -633,6 +637,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
633637
bool runForbidsLeftExpansion = m_run.expansionBehavior().left == ExpansionBehavior::Behavior::Forbid;
634638
bool runForbidsRightExpansion = m_run.expansionBehavior().right == ExpansionBehavior::Behavior::Forbid;
635639

640+
TextSpacing::CharacterClass previousCharacterClass = m_textSpacingState.lastCharacterClassFromPreviousRun;
636641
// We are iterating in glyph order, not string order. Compare this to WidthIterator::advanceInternal()
637642
for (size_t runIndex = 0; runIndex < runCount; ++runIndex) {
638643
ComplexTextRun& complexTextRun = *m_complexTextRuns[runIndex];
@@ -748,6 +753,18 @@ void ComplexTextController::adjustGlyphsAndAdvances()
748753
afterExpansion = false;
749754
}
750755

756+
const auto& textAutoSpace = m_font.textAutospace();
757+
float textAutoSpaceSpacing = 0;
758+
auto characterClass = TextSpacing::CharacterClass::Undefined;
759+
if (!textAutoSpace.isNoAutospace())
760+
characterClass = TextSpacing::characterClass(character);
761+
if (textAutoSpace.shouldApplySpacing(previousCharacterClass, characterClass)) {
762+
textAutoSpaceSpacing = complexTextRun.textAutospaceSize();
763+
advance.expand(textAutoSpaceSpacing, 0);
764+
}
765+
if (!textAutoSpace.isNoAutospace())
766+
m_textAutoSpaceSpacings.append(textAutoSpaceSpacing);
767+
751768
m_totalAdvance += advance;
752769

753770
if (m_forTextEmphasis) {
@@ -763,7 +780,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
763780
if (auto* origins = complexTextRun.glyphOrigins()) {
764781
ASSERT(m_glyphOrigins.size() < m_adjustedBaseAdvances.size());
765782
m_glyphOrigins.grow(m_adjustedBaseAdvances.size());
766-
m_glyphOrigins[m_glyphOrigins.size() - 1] = origins[glyphIndex];
783+
m_glyphOrigins[m_glyphOrigins.size() - 1] = origins[glyphIndex] + FloatSize(textAutoSpaceSpacing, 0);
767784
ASSERT(m_glyphOrigins.size() == m_adjustedBaseAdvances.size());
768785
}
769786
m_adjustedGlyphs.append(glyph);
@@ -777,6 +794,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
777794
glyphOrigin.move(advance);
778795

779796
previousCharacterIndex = characterIndex;
797+
previousCharacterClass = characterClass;
780798
}
781799
if (!isMonotonic)
782800
complexTextRun.setIsNonMonotonic();
@@ -793,6 +811,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const Font& font, const UC
793811
, m_indexEnd(indexEnd)
794812
, m_stringLocation(stringLocation)
795813
, m_isLTR(ltr)
814+
, m_textAutospaceSize(TextAutospace::textAutospaceSize(font))
796815
{
797816
auto runLengthInCodeUnits = m_indexEnd - m_indexBegin;
798817
m_coreTextIndices.reserveInitialCapacity(runLengthInCodeUnits);
@@ -832,6 +851,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const Vector<FloatSize>& a
832851
, m_glyphCount(glyphs.size())
833852
, m_stringLocation(stringLocation)
834853
, m_isLTR(ltr)
854+
, m_textAutospaceSize(TextAutospace::textAutospaceSize(font))
835855
{
836856
}
837857

Source/WebCore/platform/graphics/ComplexTextController.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include "FloatPoint.h"
2828
#include "GlyphBuffer.h"
29+
#include "TextSpacing.h"
2930
#include <wtf/HashSet.h>
3031
#include <wtf/RefCounted.h>
3132
#include <wtf/RetainPtr.h>
@@ -118,6 +119,7 @@ class ComplexTextController {
118119
bool isLTR() const { return m_isLTR; }
119120
bool isMonotonic() const { return m_isMonotonic; }
120121
void setIsNonMonotonic();
122+
float textAutospaceSize() const { return m_textAutospaceSize; }
121123

122124
private:
123125
ComplexTextRun(CTRunRef, const Font&, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd);
@@ -144,6 +146,7 @@ class ComplexTextController {
144146
unsigned m_stringLocation;
145147
bool m_isLTR;
146148
bool m_isMonotonic { true };
149+
float m_textAutospaceSize { 0 };
147150
};
148151
private:
149152
void computeExpansionOpportunity();
@@ -169,6 +172,7 @@ class ComplexTextController {
169172
Vector<FloatSize, 256> m_adjustedBaseAdvances;
170173
Vector<FloatPoint, 256> m_glyphOrigins;
171174
Vector<CGGlyph, 256> m_adjustedGlyphs;
175+
Vector<float, 256> m_textAutoSpaceSpacings;
172176

173177
Vector<UChar, 256> m_smallCapsBuffer;
174178

@@ -217,6 +221,7 @@ class ComplexTextController {
217221
bool m_isLTROnly { true };
218222
bool m_mayUseNaturalWritingDirection { false };
219223
bool m_forTextEmphasis { false };
224+
TextSpacing::SpacingState m_textSpacingState;
220225
};
221226

222227
} // namespace WebCore

Source/WebCore/platform/graphics/FontCascade.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ float FontCascade::width(const TextRun& run, SingleThreadWeakHashSet<const Font>
308308
}
309309

310310
bool hasWordSpacingOrLetterSpacing = wordSpacing() || letterSpacing();
311-
float* cacheEntry = protectedFonts()->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), enableKerning() || requiresShaping(), hasWordSpacingOrLetterSpacing, glyphOverflow);
311+
float* cacheEntry = protectedFonts()->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), enableKerning() || requiresShaping(), hasWordSpacingOrLetterSpacing, !textAutospace().isNoAutospace(), glyphOverflow);
312312
if (cacheEntry && !std::isnan(*cacheEntry))
313313
return *cacheEntry;
314314

@@ -629,6 +629,10 @@ FontCascade::CodePath FontCascade::codePath(const TextRun& run, std::optional<un
629629
if (s_codePath != CodePath::Auto)
630630
return s_codePath;
631631

632+
// FIXME: add support for text-autospace on simple path (rdar://133319627).
633+
if (textAutospace().hasIdeographAlpha())
634+
return CodePath::Complex;
635+
632636
#if !USE(FREETYPE)
633637
// FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
634638
if ((enableKerning() || requiresShaping()) && (from.value_or(0) || to.value_or(run.length()) != run.length()))

Source/WebCore/platform/graphics/GlyphBuffer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ class GlyphBuffer {
103103
add(glyph, font, advance, offsetInString);
104104
}
105105

106-
void add(Glyph glyph, const Font& font, GlyphBufferAdvance advance, GlyphBufferStringOffset offsetInString)
106+
void add(Glyph glyph, const Font& font, GlyphBufferAdvance advance, GlyphBufferStringOffset offsetInString, FloatPoint origin = { })
107107
{
108108
m_fonts.append(&font);
109109
m_glyphs.append(glyph);
110110
m_advances.append(advance);
111-
m_origins.append(makeGlyphBufferOrigin());
111+
m_origins.append(makeGlyphBufferOrigin(origin));
112112
m_offsetsInString.append(offsetInString);
113113
}
114114

Source/WebCore/platform/graphics/TextRun.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct ExpectedTextRunSize final : public CanMakeCheckedPtr<ExpectedTextRunSize>
3838
float float2;
3939
float float3;
4040
ExpansionBehavior expansionBehavior;
41+
TextSpacing::SpacingState spacingState;
4142
unsigned bitfields : 5;
4243
};
4344

Source/WebCore/platform/graphics/TextRun.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "TabSize.h"
2727
#include "TextFlags.h"
28+
#include "TextSpacing.h"
2829
#include "WritingMode.h"
2930
#include <wtf/CheckedRef.h>
3031
#include <wtf/text/StringView.h>
@@ -155,6 +156,9 @@ class TextRun final : public CanMakeCheckedPtr<TextRun> {
155156

156157
const String& textAsString() const { return m_text; }
157158

159+
void setTextSpacingState(TextSpacing::SpacingState spacingState) { m_textSpacingState = spacingState; }
160+
TextSpacing::SpacingState textSpacingState() const { return m_textSpacingState; }
161+
158162
private:
159163
String m_text;
160164

@@ -169,6 +173,9 @@ class TextRun final : public CanMakeCheckedPtr<TextRun> {
169173

170174
float m_expansion;
171175
ExpansionBehavior m_expansionBehavior;
176+
177+
TextSpacing::SpacingState m_textSpacingState;
178+
172179
unsigned m_allowTabs : 1;
173180
unsigned m_direction : 1;
174181
unsigned m_directionalOverride : 1; // Was this direction set by an override character.

0 commit comments

Comments
 (0)