Skip to content

Commit 13855c6

Browse files
committed
[text shaping] Add shaping-boundary/start/end/in-between bits to line run and display box
https://bugs.webkit.org/show_bug.cgi?id=298830 Reviewed by Antti Koivisto. This is in preparation for adding text shaping support. Line builder will set these bits on runs and TextBoxPainter will consult the display box if it needs special type of painting. * Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp: (WebCore::Layout::Line::appendText): (WebCore::Layout::Line::Run::Run): (WebCore::Layout::Line::Run::expand): * Source/WebCore/layout/formattingContexts/inline/InlineLine.h: (WebCore::Layout::Line::Run::isShapingBoundaryStart const): (WebCore::Layout::Line::Run::isShapingBoundaryEnd const): (WebCore::Layout::Line::Run::isBetweenShapingBoundaries const): (WebCore::Layout::Line::Run::isShapingBoundary const): * Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp: (WebCore::Layout::LineBuilder::commitCanidateContent): * Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h: (WebCore::InlineDisplay::Box::Text::isAtShapingBoundaryStart const): (WebCore::InlineDisplay::Box::Text::isAtShapingBoundaryEnd const): (WebCore::InlineDisplay::Box::Text::isBetweenShapingBoundaries const): (WebCore::InlineDisplay::Box::Text::Text): * Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp: (WebCore::Layout::InlineDisplayContentBuilder::appendTextDisplayBox): Canonical link: https://commits.webkit.org/300028@main
1 parent 1af87bb commit 13855c6

File tree

5 files changed

+35
-10
lines changed

5 files changed

+35
-10
lines changed

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ void Line::appendInlineBoxEnd(const InlineItem& inlineItem, const RenderStyle& s
334334
}
335335
}
336336

337-
void Line::appendText(const InlineTextItem& inlineTextItem, const RenderStyle& style, InlineLayoutUnit logicalWidth)
337+
void Line::appendText(const InlineTextItem& inlineTextItem, const RenderStyle& style, InlineLayoutUnit logicalWidth, std::optional<Line::ShapingBoundary> shapingBoundary)
338338
{
339339
auto willCollapseCompletely = [&] {
340340
if (inlineTextItem.isEmpty()) {
@@ -387,6 +387,8 @@ void Line::appendText(const InlineTextItem& inlineTextItem, const RenderStyle& s
387387
// We may end up with mismatching computed widths and misplaced glyphs at paint time -unless we keep dedicated runs with explicit positions.
388388
return true;
389389
}
390+
if (shapingBoundary || lastRun.isShapingBoundary())
391+
return true;
390392
return false;
391393
}();
392394
auto oldContentLogicalWidth = contentLogicalWidth();
@@ -399,7 +401,7 @@ void Line::appendText(const InlineTextItem& inlineTextItem, const RenderStyle& s
399401
return -TextUtil::hangablePunctuationStartWidth(inlineTextItem, style);
400402
return lastRunLogicalRight() + (inlineTextItem.isWordSeparator() ? style.fontCascade().wordSpacing() : 0.0f);
401403
}();
402-
m_runs.append({ inlineTextItem, style, runLogicalLeft, logicalWidth });
404+
m_runs.append({ inlineTextItem, style, runLogicalLeft, logicalWidth, { }, shapingBoundary });
403405
// Note that the _content_ logical right may be larger than the _run_ logical right.
404406
contentLogicalRight = runLogicalLeft + logicalWidth;
405407
} else {
@@ -786,13 +788,14 @@ Line::Run::Run(const InlineSoftLineBreakItem& softLineBreakItem, const RenderSty
786788
{
787789
}
788790

789-
Line::Run::Run(const InlineTextItem& inlineTextItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment)
791+
Line::Run::Run(const InlineTextItem& inlineTextItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment, std::optional<Line::ShapingBoundary> shapingBoundary)
790792
: m_type(inlineTextItem.isWordSeparator() ? Type::WordSeparator : inlineTextItem.isQuirkNonBreakingSpace() ? Type::NonBreakingSpace : Type::Text)
791793
, m_layoutBox(&inlineTextItem.layoutBox())
792794
, m_style(style)
793795
, m_logicalLeft(logicalLeft)
794796
, m_logicalWidth(logicalWidth)
795797
, m_bidiLevel(inlineTextItem.bidiLevel())
798+
, m_shapingBoundary(shapingBoundary)
796799
, m_textSpacingAdjustment(textSpacingAdjustment)
797800
{
798801
auto length = inlineTextItem.length();
@@ -811,6 +814,7 @@ void Line::Run::expand(const InlineTextItem& inlineTextItem, InlineLayoutUnit lo
811814
ASSERT(isText() && inlineTextItem.isText());
812815
ASSERT(m_layoutBox == &inlineTextItem.layoutBox());
813816
ASSERT(m_bidiLevel == inlineTextItem.bidiLevel());
817+
ASSERT(!m_shapingBoundary || *m_shapingBoundary != ShapingBoundary::End);
814818

815819
m_logicalWidth += logicalWidth;
816820
auto whitespaceType = trailingWhitespaceType(inlineTextItem);

Source/WebCore/layout/formattingContexts/inline/InlineLine.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Line {
4949
void initialize(const Vector<InlineItem, 1>& lineSpanningInlineBoxes, bool isFirstFormattedLine);
5050

5151
enum class ShapingBoundary : uint8_t { Start, Middle, End };
52-
void appendText(const InlineTextItem&, const RenderStyle&, InlineLayoutUnit logicalWidth);
52+
void appendText(const InlineTextItem&, const RenderStyle&, InlineLayoutUnit logicalWidth, std::optional<ShapingBoundary>);
5353
void appendTextFast(const InlineTextItem&, const RenderStyle&, InlineLayoutUnit logicalWidth); // Reserved for TextOnlySimpleLineBuilder
5454
void appendAtomicInlineBox(const InlineItem&, const RenderStyle&, InlineLayoutUnit marginBoxLogicalWidth);
5555
void appendInlineBoxStart(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment);
@@ -149,10 +149,15 @@ class Line {
149149

150150
UBiDiLevel bidiLevel() const { return m_bidiLevel; }
151151

152+
bool isShapingBoundaryStart() const { return isShapingBoundary() && *m_shapingBoundary == Line::ShapingBoundary::Start; }
153+
bool isShapingBoundaryEnd() const { return isShapingBoundary() && *m_shapingBoundary == Line::ShapingBoundary::End; }
154+
bool isBetweenShapingBoundaries() const { return isShapingBoundary() && *m_shapingBoundary == Line::ShapingBoundary::Middle; }
155+
bool isShapingBoundary() const { return m_shapingBoundary.has_value(); }
156+
152157
// FIXME: Maybe add create functions intead?
153158
Run(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalLeft);
154159
Run(const InlineItem& lineSpanningInlineBoxItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment = 0.f);
155-
Run(const InlineTextItem&, const RenderStyle&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment = 0.f);
160+
Run(const InlineTextItem&, const RenderStyle&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit textSpacingAdjustment = 0.f, std::optional<Line::ShapingBoundary> = std::nullopt);
156161

157162
private:
158163
friend class Line;
@@ -201,6 +206,7 @@ class Line {
201206
std::optional<TrailingWhitespace> m_trailingWhitespace { };
202207
std::optional<size_t> m_lastNonWhitespaceContentStart { };
203208
std::optional<Text> m_textContent;
209+
std::optional<Line::ShapingBoundary> m_shapingBoundary;
204210
InlineLayoutUnit m_textSpacingAdjustment { 0 };
205211
};
206212
using RunList = Vector<Run, 10>;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ void LineBuilder::commitCanidateContent(const LineCandidate& lineCandidate, std:
12431243
m_line.setContentNeedsBidiReordering();
12441244

12451245
if (auto* inlineTextItem = dynamicDowncast<InlineTextItem>(inlineItem)) {
1246-
m_line.appendText(*inlineTextItem, run.style, run.contentWidth());
1246+
m_line.appendText(*inlineTextItem, run.style, run.contentWidth(), { });
12471247
return;
12481248
}
12491249

@@ -1297,7 +1297,7 @@ void LineBuilder::commitCanidateContent(const LineCandidate& lineCandidate, std:
12971297
// Create and commit partial trailing item.
12981298
if (auto* trailingInlineTextItem = dynamicDowncast<InlineTextItem>(runs[trailingRunIndex].inlineItem)) {
12991299
auto partialTrailingTextItem = trailingInlineTextItem->left(partialRun->length);
1300-
m_line.appendText(partialTrailingTextItem, trailingInlineTextItem->style(), partialRun->logicalWidth);
1300+
m_line.appendText(partialTrailingTextItem, trailingInlineTextItem->style(), partialRun->logicalWidth, { });
13011301
if (trailingInlineTextItem->bidiLevel() != UBIDI_DEFAULT_LTR)
13021302
m_line.setContentNeedsBidiReordering();
13031303
} else

Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,17 @@ struct Box {
4242
struct Text {
4343
public:
4444
Text() = default;
45-
Text(size_t position, size_t length, const String& originalContent, String adjustedContentToRender = String(), bool hasHyphen = false);
45+
enum ShapingBoundary : uint8_t { Start, Inside, End, NotApplicable };
46+
Text(size_t position, size_t length, const String& originalContent, String adjustedContentToRender = String(), bool hasHyphen = false, ShapingBoundary = ShapingBoundary::NotApplicable);
4647

4748
size_t start() const { return m_start; }
4849
size_t end() const { return start() + length(); }
4950
size_t length() const { return m_length; }
5051
StringView originalContent() const { return StringView(m_originalContent).substring(m_start, m_length); }
5152
StringView renderedContent() const { return m_adjustedContentToRender.isNull() ? originalContent() : m_adjustedContentToRender; }
53+
bool isAtShapingBoundaryStart() const { return m_shapingBoundary == ShapingBoundary::Start; }
54+
bool isAtShapingBoundaryEnd() const { return m_shapingBoundary == ShapingBoundary::End; }
55+
bool isBetweenShapingBoundaries() const { return m_shapingBoundary == ShapingBoundary::Inside; }
5256
bool hasHyphen() const { return m_hasHyphen; }
5357
std::optional<size_t> partiallyVisibleContentLength() const;
5458
void setPartiallyVisibleContentLength(size_t truncatedLength);
@@ -61,6 +65,7 @@ struct Box {
6165

6266
unsigned m_start { 0 };
6367
unsigned m_length { 0 };
68+
ShapingBoundary m_shapingBoundary { ShapingBoundary::NotApplicable };
6469
unsigned m_partiallyVisibleContentLength : 30 { };
6570
bool m_hasPartiallyVisibleContentLength : 1 { false };
6671
bool m_hasHyphen : 1 { false };
@@ -212,11 +217,12 @@ inline Box::~Box()
212217
removeBoxFromGlyphDisplayListCache(*this);
213218
}
214219

215-
inline Box::Text::Text(size_t start, size_t length, const String& originalContent, String adjustedContentToRender, bool hasHyphen)
220+
inline Box::Text::Text(size_t start, size_t length, const String& originalContent, String adjustedContentToRender, bool hasHyphen, ShapingBoundary shapingBoundary)
216221
: m_originalContent(originalContent)
217222
, m_adjustedContentToRender(adjustedContentToRender)
218223
, m_start(start)
219224
, m_length(length)
225+
, m_shapingBoundary(shapingBoundary)
220226
, m_hasHyphen(hasHyphen)
221227
{
222228
}

Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,15 @@ void InlineDisplayContentBuilder::appendTextDisplayBox(const Line::Run& lineRun,
235235
auto adjustedContentToRender = [&] {
236236
return text->needsHyphen ? makeString(StringView(content).substring(text->start, text->length), style.hyphenString()) : String();
237237
};
238+
auto shapingBoundary = [&] {
239+
if (lineRun.isShapingBoundaryStart())
240+
return InlineDisplay::Box::Text::ShapingBoundary::Start;
241+
if (lineRun.isShapingBoundaryEnd())
242+
return InlineDisplay::Box::Text::ShapingBoundary::End;
243+
if (lineRun.isBetweenShapingBoundaries())
244+
return InlineDisplay::Box::Text::ShapingBoundary::Inside;
245+
return InlineDisplay::Box::Text::ShapingBoundary::NotApplicable;
246+
};
238247
boxes.append({ lineIndex()
239248
, lineRun.isWordSeparator() ? InlineDisplay::Box::Type::WordSeparator : InlineDisplay::Box::Type::Text
240249
, inlineTextBox
@@ -243,7 +252,7 @@ void InlineDisplayContentBuilder::appendTextDisplayBox(const Line::Run& lineRun,
243252
, inkOverflow
244253
, isFirstFormattedLine()
245254
, lineRun.expansion()
246-
, InlineDisplay::Box::Text { text->start, text->length, content, adjustedContentToRender(), text->needsHyphen }
255+
, InlineDisplay::Box::Text { text->start, text->length, content, adjustedContentToRender(), text->needsHyphen, shapingBoundary() }
247256
, isContentful
248257
, isLineFullyTruncatedInBlockDirection()
249258
});

0 commit comments

Comments
 (0)