Changeset 269769 in webkit


Ignore:
Timestamp:
Nov 13, 2020 4:07:38 AM (3 years ago)
Author:
Alan Bujtas
Message:

[LFC][Integration] Decouple box and text run construction
https://bugs.webkit.org/show_bug.cgi?id=218882

Reviewed by Antti Koivisto.

This is in preparation for adding bidi support where we may need to split a run on bidi boundaries.

  • layout/integration/LayoutIntegrationInlineContentBuilder.cpp:

(WebCore::LayoutIntegration::InlineContentBuilder::constructDisplayLineRuns const):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r269768 r269769  
     12020-11-13  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][Integration] Decouple box and text run construction
     4        https://bugs.webkit.org/show_bug.cgi?id=218882
     5
     6        Reviewed by Antti Koivisto.
     7
     8        This is in preparation for adding bidi support where we may need to split a run on bidi boundaries.
     9
     10        * layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
     11        (WebCore::LayoutIntegration::InlineContentBuilder::constructDisplayLineRuns const):
     12
    1132020-11-13  Kimmo Kinnunen  <kkinnunen@apple.com>
    214
  • trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp

    r269571 r269769  
    109109void InlineContentBuilder::constructDisplayLineRuns(InlineContent& inlineContent, const Layout::InlineFormattingState& inlineFormattingState, const LineLevelVisualAdjustmentsForRunsList& lineLevelVisualAdjustmentsForRuns) const
    110110{
     111    auto& runList = inlineFormattingState.lineRuns();
     112    if (runList.isEmpty())
     113        return;
    111114    auto& lines = inlineFormattingState.lines();
    112     auto initialContaingBlockSize = m_layoutState.viewportSize();
    113115    Vector<bool> hasAdjustedTrailingLineList(lines.size(), false);
    114     for (auto& lineRun : inlineFormattingState.lineRuns()) {
     116
     117    auto createDisplayBoxRun = [&](auto& lineRun) {
     118        auto lineIndex = lineRun.lineIndex();
     119        auto& line = lines[lineIndex];
     120        // Inline boxes are relative to the line box while final Runs need to be relative to the parent Box
     121        // FIXME: Shouldn't we just leave them be relative to the line box?
     122        auto runRect = FloatRect { lineRun.logicalRect() };
     123        runRect.moveBy({ line.logicalLeft(), line.logicalTop() });
     124        if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition)
     125            runRect.setY(roundToInt(runRect.y()));
     126        // FIXME: Add support for non-text ink overflow.
     127        // FIXME: Add support for cases when the run is after ellipsis.
     128        inlineContent.runs.append({ lineIndex, lineRun.layoutBox(), runRect, runRect, { }, { } });
     129    };
     130
     131    auto createDisplayTextRunForRange = [&](auto& lineRun, auto startOffset, auto endOffset) {
     132        RELEASE_ASSERT(startOffset < endOffset);
    115133        auto& layoutBox = lineRun.layoutBox();
     134        auto lineIndex = lineRun.lineIndex();
     135        auto& line = lines[lineIndex];
     136        auto runRect = FloatRect { lineRun.logicalRect() };
     137        // Inline boxes are relative to the line box while final Runs need to be relative to the parent Box
     138        // FIXME: Shouldn't we just leave them be relative to the line box?
     139        runRect.moveBy({ line.logicalLeft(), line.logicalTop() });
     140        if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition)
     141            runRect.setY(roundToInt(runRect.y()));
     142
    116143        auto& style = layoutBox.style();
     144        auto text = lineRun.text();
     145        auto adjustedContentToRenderer = [&] {
     146            auto originalContent = text->content().substring(text->start(), text->length());
     147            if (text->needsHyphen())
     148                return makeString(originalContent, style.hyphenString());
     149            if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsTrailingContentReplacement) {
     150                // Currently it's ellipsis replacement only, but adding support for "text-overflow: string" should be relatively simple.
     151                if (hasAdjustedTrailingLineList[lineIndex]) {
     152                    // This line already has adjusted trailing. Any runs after the ellipsis should render blank.
     153                    return emptyString();
     154                }
     155                auto runLogicalRect = lineRun.logicalRect();
     156                auto lineLogicalRight = line.logicalRight();
     157                auto ellipsisWidth = style.fontCascade().width(WebCore::TextRun { &horizontalEllipsis });
     158                if (runLogicalRect.right() + ellipsisWidth > lineLogicalRight) {
     159                    // The next run with ellipsis would surely overflow. So let's just add it to this run even if
     160                    // it makes the run wider than it originally was.
     161                    hasAdjustedTrailingLineList[lineIndex] = true;
     162                    float resultWidth = 0;
     163                    auto maxWidth = line.logicalWidth() - runLogicalRect.left();
     164                    return StringTruncator::rightTruncate(originalContent, maxWidth, style.fontCascade(), resultWidth, true);
     165                }
     166            }
     167            return String();
     168        };
     169
    117170        auto computedInkOverflow = [&] (auto runRect) {
    118             // FIXME: Add support for non-text ink overflow.
    119             if (!lineRun.text())
    120                 return runRect;
    121171            auto inkOverflow = runRect;
     172            auto initialContaingBlockSize = m_layoutState.viewportSize();
    122173            auto strokeOverflow = std::ceil(style.computedStrokeWidth(ceiledIntSize(initialContaingBlockSize)));
    123174            inkOverflow.inflate(strokeOverflow);
    124 
    125175            auto letterSpacing = style.fontCascade().letterSpacing();
    126176            if (letterSpacing < 0) {
     
    130180            return inkOverflow;
    131181        };
    132         auto runRect = FloatRect { lineRun.logicalRect() };
    133         // Inline boxes are relative to the line box while final Runs need to be relative to the parent Box
    134         // FIXME: Shouldn't we just leave them be relative to the line box?
    135         auto lineIndex = lineRun.lineIndex();
    136         auto& line = lines[lineIndex];
    137         runRect.moveBy({ line.logicalLeft(), line.logicalTop() });
    138         if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition)
    139             runRect.setY(roundToInt(runRect.y()));
    140 
    141         WTF::Optional<Run::TextContent> textContent;
    142         if (auto text = lineRun.text()) {
    143             auto adjustedContentToRenderer = [&] {
    144                 auto originalContent = text->content().substring(text->start(), text->length());
    145                 if (text->needsHyphen())
    146                     return makeString(originalContent, style.hyphenString());
    147                 if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsTrailingContentReplacement) {
    148                     // Currently it's ellipsis replacement only, but adding support for "text-overflow: string" should be relatively simple.
    149                     if (hasAdjustedTrailingLineList[lineIndex]) {
    150                         // This line already has adjusted trailing. Any runs after the ellipsis should render blank.
    151                         return emptyString();
    152                     }
    153                     auto runLogicalRect = lineRun.logicalRect();
    154                     auto lineLogicalRight = line.logicalRight();
    155                     auto ellipsisWidth = style.fontCascade().width(WebCore::TextRun { &horizontalEllipsis });
    156                     if (runLogicalRect.right() + ellipsisWidth > lineLogicalRight) {
    157                         // The next run with ellipsis would surely overflow. So let's just add it to this run even if
    158                         // it makes the run wider than it originally was.
    159                         hasAdjustedTrailingLineList[lineIndex] = true;
    160                         float resultWidth = 0;
    161                         auto maxWidth = line.logicalWidth() - runLogicalRect.left();
    162                         return StringTruncator::rightTruncate(originalContent, maxWidth, style.fontCascade(), resultWidth, true);
    163                     }
    164                 }
    165                 return String();
    166             };
    167             textContent = Run::TextContent { text->start(), text->length(), text->content(), adjustedContentToRenderer(), text->needsHyphen() };
    168         }
     182        RELEASE_ASSERT(startOffset >= text->start() && startOffset < text->end());
     183        RELEASE_ASSERT(endOffset > text->start() && endOffset <= text->end());
     184        auto textContent = Run::TextContent { startOffset, endOffset - startOffset, text->content(), adjustedContentToRenderer(), text->needsHyphen() };
    169185        auto expansion = Run::Expansion { lineRun.expansion().behavior, lineRun.expansion().horizontalExpansion };
    170186        auto displayRun = Run { lineIndex, layoutBox, runRect, computedInkOverflow(runRect), expansion, textContent };
    171187        inlineContent.runs.append(displayRun);
     188    };
     189
     190    for (auto& lineRun : inlineFormattingState.lineRuns()) {
     191        if (auto& text = lineRun.text())
     192            createDisplayTextRunForRange(lineRun, text->start(), text->end());
     193        else
     194            createDisplayBoxRun(lineRun);
    172195    }
    173196}
Note: See TracChangeset for help on using the changeset viewer.