Changeset 270025 in webkit


Ignore:
Timestamp:
Nov 19, 2020 6:17:12 AM (3 years ago)
Author:
Antti Koivisto
Message:

[LFC][Integration] nextLinePosition should use iterator
https://bugs.webkit.org/show_bug.cgi?id=219152

Reviewed by Zalan Bujtas.

The last major piece of direct InlineBox access in editing code.

  • dom/Position.cpp:

(WebCore::InlineBoxAndOffset::InlineBoxAndOffset): Deleted.
(WebCore::Position::inlineBoxAndOffset const): Deleted.

No longer needed.

  • dom/Position.h:
  • editing/VisibleUnits.cpp:

(WebCore::previousLineCandidatePosition):
(WebCore::nextLineCandidatePosition):
(WebCore::isTextOrLineBreakRun):
(WebCore::previousTextOrLineBreakRun):
(WebCore::nextTextOrLineBreakRun):
(WebCore::startTextOrLineBreakRun):
(WebCore::endTextOrLineBreakRun):
(WebCore::logicallyPreviousRun):
(WebCore::logicallyNextRun):
(WebCore::wordBreakIteratorForMinOffsetBoundary):
(WebCore::wordBreakIteratorForMaxOffsetBoundary):
(WebCore::visualWordPosition):
(WebCore::previousLinePosition):
(WebCore::nextLinePosition):
(WebCore::previousRootInlineBoxCandidatePosition): Deleted.
(WebCore::nextRootInlineBoxCandidatePosition): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::size const): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::firstBox const): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::previousTextOrLineBreakBox): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::nextTextOrLineBreakBox): Deleted.
(WebCore::CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves const): Deleted.

The iterarator handles logical order caching for InlineBoxes, no need for a separate cache.

(WebCore::logicallyPreviousBox): Deleted.
(WebCore::logicallyNextBox): Deleted.

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r270024 r270025  
     12020-11-19  Antti Koivisto  <antti@apple.com>
     2
     3        [LFC][Integration] nextLinePosition should use iterator
     4        https://bugs.webkit.org/show_bug.cgi?id=219152
     5
     6        Reviewed by Zalan Bujtas.
     7
     8        The last major piece of direct InlineBox access in editing code.
     9
     10        * dom/Position.cpp:
     11        (WebCore::InlineBoxAndOffset::InlineBoxAndOffset): Deleted.
     12        (WebCore::Position::inlineBoxAndOffset const): Deleted.
     13
     14        No longer needed.
     15
     16        * dom/Position.h:
     17        * editing/VisibleUnits.cpp:
     18        (WebCore::previousLineCandidatePosition):
     19        (WebCore::nextLineCandidatePosition):
     20        (WebCore::isTextOrLineBreakRun):
     21        (WebCore::previousTextOrLineBreakRun):
     22        (WebCore::nextTextOrLineBreakRun):
     23        (WebCore::startTextOrLineBreakRun):
     24        (WebCore::endTextOrLineBreakRun):
     25        (WebCore::logicallyPreviousRun):
     26        (WebCore::logicallyNextRun):
     27        (WebCore::wordBreakIteratorForMinOffsetBoundary):
     28        (WebCore::wordBreakIteratorForMaxOffsetBoundary):
     29        (WebCore::visualWordPosition):
     30        (WebCore::previousLinePosition):
     31        (WebCore::nextLinePosition):
     32        (WebCore::previousRootInlineBoxCandidatePosition): Deleted.
     33        (WebCore::nextRootInlineBoxCandidatePosition): Deleted.
     34        (WebCore::CachedLogicallyOrderedLeafBoxes::size const): Deleted.
     35        (WebCore::CachedLogicallyOrderedLeafBoxes::firstBox const): Deleted.
     36        (WebCore::CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes): Deleted.
     37        (WebCore::CachedLogicallyOrderedLeafBoxes::previousTextOrLineBreakBox): Deleted.
     38        (WebCore::CachedLogicallyOrderedLeafBoxes::nextTextOrLineBreakBox): Deleted.
     39        (WebCore::CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves const): Deleted.
     40
     41        The iterarator handles logical order caching for InlineBoxes, no need for a separate cache.
     42
     43        (WebCore::logicallyPreviousBox): Deleted.
     44        (WebCore::logicallyNextBox): Deleted.
     45
    1462020-11-19  Carlos Garcia Campos  <cgarcia@igalia.com>
    247
  • trunk/Source/WebCore/dom/Position.cpp

    r269852 r270025  
    104104}
    105105
    106 InlineBoxAndOffset::InlineBoxAndOffset(InlineRunAndOffset runAndOffset)
    107     : box(runAndOffset.run ? runAndOffset.run->legacyInlineBox() : nullptr)
    108     , offset(runAndOffset.offset)
    109 {
    110 }
    111 
    112106Position::Position(Node* anchorNode, unsigned offset, LegacyEditingPositionFlag)
    113107    : m_anchorNode(anchorNode)
     
    13701364}
    13711365
    1372 InlineBoxAndOffset Position::inlineBoxAndOffset(Affinity affinity) const
    1373 {
    1374     return inlineBoxAndOffset(affinity, primaryDirection());
    1375 }
    1376 
    1377 InlineBoxAndOffset Position::inlineBoxAndOffset(Affinity affinity, TextDirection primaryDirection) const
    1378 {
    1379     ensureLineBoxes();
    1380 
    1381     return { inlineRunAndOffset(affinity, primaryDirection) };
    1382 }
    1383 
    13841366void Position::ensureLineBoxes() const
    13851367{
  • trunk/Source/WebCore/dom/Position.h

    r269442 r270025  
    5252struct InlineRunAndOffset;
    5353
    54 struct InlineBoxAndOffset {
    55     InlineBoxAndOffset(InlineRunAndOffset);
    56 
    57     InlineBox* box { nullptr };
    58     int offset { 0 };
    59 };
    60 
    6154class Position {
    6255public:
     
    180173    InlineRunAndOffset inlineRunAndOffset(Affinity, TextDirection primaryDirection) const;
    181174
    182     InlineBoxAndOffset inlineBoxAndOffset(Affinity) const;
    183     InlineBoxAndOffset inlineBoxAndOffset(Affinity, TextDirection primaryDirection) const;
    184 
    185175    TextDirection primaryDirection() const;
    186176
  • trunk/Source/WebCore/editing/VisibleUnits.cpp

    r269732 r270025  
    11/*
    2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333#include "HTMLNames.h"
    3434#include "InlineRunAndOffset.h"
    35 #include "InlineTextBox.h"
     35#include "LayoutIntegrationLineIterator.h"
     36#include "LayoutIntegrationRunIterator.h"
    3637#include "NodeTraversal.h"
    3738#include "Range.h"
     
    7980
    8081// FIXME: consolidate with code in previousLinePosition.
    81 static Position previousRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
     82static Position previousLineCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
    8283{
    8384    auto* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
     
    102103}
    103104
    104 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
     105static Position nextLineCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
    105106{
    106107    auto* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
     
    124125}
    125126
    126 class CachedLogicallyOrderedLeafBoxes {
    127 public:
    128     CachedLogicallyOrderedLeafBoxes();
    129 
    130     const InlineBox* previousTextOrLineBreakBox(const RootInlineBox*, const InlineBox*);
    131     const InlineBox* nextTextOrLineBreakBox(const RootInlineBox*, const InlineBox*);
    132 
    133     size_t size() const { return m_leafBoxes.size(); }
    134     const InlineBox* firstBox() const { return m_leafBoxes[0]; }
    135 
    136 private:
    137     const Vector<InlineBox*>& collectBoxes(const RootInlineBox*);
    138     int boxIndexInLeaves(const InlineBox*) const;
    139 
    140     const RootInlineBox* m_rootInlineBox { nullptr };
    141     Vector<InlineBox*> m_leafBoxes;
    142 };
    143 
    144 CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes()
    145 {
    146 }
    147 
    148 const InlineBox* CachedLogicallyOrderedLeafBoxes::previousTextOrLineBreakBox(const RootInlineBox* root, const InlineBox* box)
    149 {
    150     if (!root)
    151         return nullptr;
    152 
    153     collectBoxes(root);
    154 
    155     // If box is null, root is box's previous RootInlineBox, and previousBox is the last logical box in root.
    156     int boxIndex = m_leafBoxes.size() - 1;
    157     if (box)
    158         boxIndex = boxIndexInLeaves(box) - 1;
    159 
    160     for (int i = boxIndex; i >= 0; --i) {
    161         InlineBox* box = m_leafBoxes[i];
    162         if (box->isInlineTextBox() || box->renderer().isBR())
    163             return box;
    164     }
    165 
    166     return nullptr;
    167 }
    168 
    169 const InlineBox* CachedLogicallyOrderedLeafBoxes::nextTextOrLineBreakBox(const RootInlineBox* root, const InlineBox* box)
    170 {
    171     if (!root)
    172         return nullptr;
    173 
    174     collectBoxes(root);
    175 
    176     // If box is null, root is box's next RootInlineBox, and nextBox is the first logical box in root.
    177     // Otherwise, root is box's RootInlineBox, and nextBox is the next logical box in the same line.
    178     size_t nextBoxIndex = 0;
    179     if (box)
    180         nextBoxIndex = boxIndexInLeaves(box) + 1;
    181 
    182     for (size_t i = nextBoxIndex; i < m_leafBoxes.size(); ++i) {
    183         InlineBox* box = m_leafBoxes[i];
    184         if (box->isInlineTextBox() || box->renderer().isBR())
    185             return box;
    186     }
    187 
    188     return nullptr;
    189 }
    190 
    191 const Vector<InlineBox*>& CachedLogicallyOrderedLeafBoxes::collectBoxes(const RootInlineBox* root)
    192 {
    193     if (m_rootInlineBox != root) {
    194         m_rootInlineBox = root;
    195         m_leafBoxes.clear();
    196         root->collectLeafBoxesInLogicalOrder(m_leafBoxes);
    197     }
    198     return m_leafBoxes;
    199 }
    200 
    201 int CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves(const InlineBox* box) const
    202 {
    203     for (size_t i = 0; i < m_leafBoxes.size(); ++i) {
    204         if (box == m_leafBoxes[i])
    205             return i;
    206     }
    207     return 0;
    208 }
    209 
    210 static const InlineBox* logicallyPreviousBox(const VisiblePosition& visiblePosition, const InlineBox* textBox,
    211     bool& previousBoxInDifferentLine, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    212 {
    213     const InlineBox* startBox = textBox;
    214 
    215     const InlineBox* previousBox = leafBoxes.previousTextOrLineBreakBox(&startBox->root(), textBox);
    216     if (previousBox)
    217         return previousBox;
    218 
    219     previousBox = leafBoxes.previousTextOrLineBreakBox(startBox->root().prevRootBox(), 0);
    220     if (previousBox)
    221         return previousBox;
     127static bool isTextOrLineBreakRun(LayoutIntegration::RunIterator run)
     128{
     129    return run && (run->isText() || run->renderer().isBR());
     130}
     131
     132static LayoutIntegration::RunIterator previousTextOrLineBreakRun(LayoutIntegration::RunIterator run)
     133{
     134    while (run) {
     135        run.traversePreviousOnLineInLogicalOrder();
     136        if (isTextOrLineBreakRun(run))
     137            return run;
     138    }
     139    return { };
     140}
     141
     142static LayoutIntegration::RunIterator nextTextOrLineBreakRun(LayoutIntegration::RunIterator run)
     143{
     144    while (run) {
     145        run.traverseNextOnLineInLogicalOrder();
     146        if (isTextOrLineBreakRun(run))
     147            return run;
     148    }
     149    return { };
     150}
     151
     152static LayoutIntegration::RunIterator startTextOrLineBreakRun(LayoutIntegration::LineIterator line)
     153{
     154    auto run = line.logicalStartRun();
     155    if (isTextOrLineBreakRun(run))
     156        return run;
     157    return nextTextOrLineBreakRun(run);
     158}
     159
     160static LayoutIntegration::RunIterator endTextOrLineBreakRun(LayoutIntegration::LineIterator line)
     161{
     162    auto run = line.logicalEndRun();
     163    if (isTextOrLineBreakRun(run))
     164        return run;
     165    return previousTextOrLineBreakRun(run);
     166}
     167
     168static const LayoutIntegration::RunIterator logicallyPreviousRun(const VisiblePosition& visiblePosition, LayoutIntegration::RunIterator startRun, bool& previousBoxInDifferentLine)
     169{
     170    if (auto previousRun = previousTextOrLineBreakRun(startRun))
     171        return previousRun;
     172
     173    if (auto previousLine = startRun.line().previous()) {
     174        // FIXME: Why isn't previousBoxInDifferentLine set here?
     175        if (auto previousRun = endTextOrLineBreakRun(previousLine))
     176            return previousRun;
     177    }
    222178
    223179    while (1) {
    224         Node* startNode = startBox->renderer().nonPseudoNode();
     180        auto* startNode = startRun->renderer().nonPseudoNode();
    225181        if (!startNode)
    226182            break;
    227183
    228         Position position = previousRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
     184        Position position = previousLineCandidatePosition(startNode, visiblePosition, ContentIsEditable);
    229185        if (position.isNull())
    230186            break;
    231187
    232188        RenderedPosition renderedPosition(position, Affinity::Downstream);
    233         RootInlineBox* previousRoot = renderedPosition.rootBox();
    234         if (!previousRoot)
    235             break;
    236 
    237         previousBox = leafBoxes.previousTextOrLineBreakBox(previousRoot, &startBox->root() == previousRoot ? startBox : nullptr);
    238         if (previousBox) {
    239             previousBoxInDifferentLine = true;
    240             return previousBox;
    241         }
    242 
    243         if (!leafBoxes.size())
    244             break;
    245         startBox = leafBoxes.firstBox();
    246     }
    247     return 0;
    248 }
    249 
    250 
    251 static const InlineBox* logicallyNextBox(const VisiblePosition& visiblePosition, const InlineBox* textBox,
    252     bool& nextBoxInDifferentLine, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    253 {
    254     const InlineBox* startBox = textBox;
    255 
    256     const InlineBox* nextBox = leafBoxes.nextTextOrLineBreakBox(&startBox->root(), textBox);
    257     if (nextBox)
    258         return nextBox;
    259 
    260     nextBox = leafBoxes.nextTextOrLineBreakBox(startBox->root().nextRootBox(), 0);
    261     if (nextBox)
    262         return nextBox;
     189        auto previousLine = renderedPosition.line();
     190        if (!previousLine)
     191            break;
     192
     193        if (previousLine != startRun.line()) {
     194            if (auto previousRun = endTextOrLineBreakRun(previousLine)) {
     195                previousBoxInDifferentLine = true;
     196                return previousRun;
     197            }
     198        }
     199
     200        startRun = previousLine.logicalStartRun();
     201    }
     202    return { };
     203}
     204
     205
     206static const LayoutIntegration::RunIterator logicallyNextRun(const VisiblePosition& visiblePosition, LayoutIntegration::RunIterator startRun, bool& nextBoxInDifferentLine)
     207{
     208    if (auto nextRun = nextTextOrLineBreakRun(startRun))
     209        return nextRun;
     210
     211    if (auto nextLine = startRun.line().next()) {
     212        // FIXME: Why isn't previousBoxInDifferentLine set here?
     213        if (auto nextRun = startTextOrLineBreakRun(nextLine))
     214            return nextRun;
     215    }
    263216
    264217    while (1) {
    265         Node* startNode = startBox->renderer().nonPseudoNode();
     218        auto* startNode = startRun->renderer().nonPseudoNode();
    266219        if (!startNode)
    267220            break;
    268221
    269         Position position = nextRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
     222        Position position = nextLineCandidatePosition(startNode, visiblePosition, ContentIsEditable);
    270223        if (position.isNull())
    271224            break;
    272225
    273226        RenderedPosition renderedPosition(position, Affinity::Downstream);
    274         RootInlineBox* nextRoot = renderedPosition.rootBox();
    275         if (!nextRoot)
    276             break;
    277 
    278         nextBox = leafBoxes.nextTextOrLineBreakBox(nextRoot, &startBox->root() == nextRoot ? startBox : nullptr);
    279         if (nextBox) {
    280             nextBoxInDifferentLine = true;
    281             return nextBox;
    282         }
    283 
    284         if (!leafBoxes.size())
    285             break;
    286         startBox = leafBoxes.firstBox();
    287     }
    288     return 0;
    289 }
    290 
    291 static UBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    292     int& previousBoxLength, bool& previousBoxInDifferentLine, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    293 {
    294     previousBoxInDifferentLine = false;
    295 
    296     const InlineBox* previousBox = logicallyPreviousBox(visiblePosition, textBox, previousBoxInDifferentLine, leafBoxes);
    297     while (previousBox && !is<InlineTextBox>(previousBox)) {
    298         ASSERT(previousBox->renderer().isBR());
    299         previousBoxInDifferentLine = true;
    300         previousBox = logicallyPreviousBox(visiblePosition, previousBox, previousBoxInDifferentLine, leafBoxes);
     227        auto nextLine = renderedPosition.line();
     228        if (!nextLine)
     229            break;
     230
     231        if (nextLine != startRun.line()) {
     232            if (auto nextRun = startTextOrLineBreakRun(nextLine)) {
     233                nextBoxInDifferentLine = true;
     234                return nextRun;
     235            }
     236        }
     237
     238        startRun = nextLine.logicalEndRun();
     239    }
     240    return { };
     241}
     242
     243static UBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePosition& visiblePosition, LayoutIntegration::TextRunIterator textRun,
     244    unsigned& previousRunLength, bool& previousRunInDifferentLine, Vector<UChar, 1024>& string)
     245{
     246    previousRunInDifferentLine = false;
     247
     248    auto previousRun = logicallyPreviousRun(visiblePosition, textRun, previousRunInDifferentLine);
     249    while (previousRun && !previousRun->isText()) {
     250        ASSERT(previousRun->renderer().isBR());
     251        previousRunInDifferentLine = true;
     252        previousRun = logicallyPreviousRun(visiblePosition, previousRun, previousRunInDifferentLine);
    301253    }
    302254
    303255    string.clear();
    304256
    305     if (is<InlineTextBox>(previousBox)) {
    306         const auto& previousTextBox = downcast<InlineTextBox>(*previousBox);
    307         previousBoxLength = previousTextBox.len();
    308         append(string, StringView(previousTextBox.renderer().text()).substring(previousTextBox.start(), previousBoxLength));
    309     }
    310     append(string, StringView(textBox->renderer().text()).substring(textBox->start(), textBox->len()));
     257    if (previousRun) {
     258        auto& previousTextRun = downcast<LayoutIntegration::TextRunIterator>(previousRun);
     259        previousRunLength = previousTextRun->length();
     260        append(string, previousTextRun->text());
     261    }
     262    append(string, textRun->text());
    311263
    312264    return wordBreakIterator(StringView(string.data(), string.size()));
    313265}
    314266
    315 static UBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    316     bool& nextBoxInDifferentLine, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    317 {
    318     nextBoxInDifferentLine = false;
    319 
    320     const InlineBox* nextBox = logicallyNextBox(visiblePosition, textBox, nextBoxInDifferentLine, leafBoxes);
    321     while (nextBox && !is<InlineTextBox>(nextBox)) {
    322         ASSERT(nextBox->renderer().isBR());
    323         nextBoxInDifferentLine = true;
    324         nextBox = logicallyNextBox(visiblePosition, nextBox, nextBoxInDifferentLine, leafBoxes);
     267static UBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePosition& visiblePosition, LayoutIntegration::TextRunIterator textRun,
     268    bool& nextRunInDifferentLine, Vector<UChar, 1024>& string)
     269{
     270    nextRunInDifferentLine = false;
     271
     272    auto nextRun = logicallyNextRun(visiblePosition, textRun, nextRunInDifferentLine);
     273    while (nextRun && !nextRun->isText()) {
     274        ASSERT(nextRun->renderer().isBR());
     275        nextRunInDifferentLine = true;
     276        nextRun = logicallyNextRun(visiblePosition, nextRun, nextRunInDifferentLine);
    325277    }
    326278
    327279    string.clear();
    328     append(string, StringView(textBox->renderer().text()).substring(textBox->start(), textBox->len()));
    329     if (is<InlineTextBox>(nextBox)) {
    330         const auto& nextTextBox = downcast<InlineTextBox>(*nextBox);
    331         append(string, StringView(nextTextBox.renderer().text()).substring(nextTextBox.start(), nextTextBox.len()));
     280    append(string, textRun->text());
     281
     282    if (nextRun) {
     283        auto& nextTextRun = downcast<LayoutIntegration::TextRunIterator>(nextRun);
     284        append(string, nextTextRun->text());
    332285    }
    333286
     
    361314
    362315    TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
    363     InlineBox* previouslyVisitedBox = nullptr;
     316    LayoutIntegration::RunIterator previouslyVisitedRun;
    364317    VisiblePosition current = visiblePosition;
    365318    Optional<VisiblePosition> previousPosition;
    366319    UBreakIterator* iter = nullptr;
    367320
    368     CachedLogicallyOrderedLeafBoxes leafBoxes;
    369321    Vector<UChar, 1024> string;
    370322
     
    377329            return VisiblePosition();
    378330   
    379         // FIXME: Why force the use of upstream affinity here instead of VisiblePosition::inlineBoxAndOffset, which will get affinity from adjacentCharacterPosition?
    380         auto [box, offsetInBox] = adjacentCharacterPosition.deepEquivalent().inlineBoxAndOffset(Affinity::Upstream);
    381    
    382         if (!box)
    383             break;
    384         if (!is<InlineTextBox>(*box)) {
     331        // FIXME: Why force the use of upstream affinity here instead of VisiblePosition::inlineRunAndOffset, which will get affinity from adjacentCharacterPosition?
     332        auto [run, offsetInRun] = adjacentCharacterPosition.deepEquivalent().inlineRunAndOffset(Affinity::Upstream);
     333   
     334        if (!run)
     335            break;
     336        if (!run->isText()) {
    385337            current = adjacentCharacterPosition;
    386338            continue;
    387339        }
    388340
    389         InlineTextBox& textBox = downcast<InlineTextBox>(*box);
    390         int previousBoxLength = 0;
    391         bool previousBoxInDifferentLine = false;
    392         bool nextBoxInDifferentLine = false;
    393         bool movingIntoNewBox = previouslyVisitedBox != box;
    394 
    395         if (offsetInBox == box->caretMinOffset())
    396             iter = wordBreakIteratorForMinOffsetBoundary(adjacentCharacterPosition, &textBox, previousBoxLength, previousBoxInDifferentLine, string, leafBoxes);
    397         else if (offsetInBox == box->caretMaxOffset())
    398             iter = wordBreakIteratorForMaxOffsetBoundary(adjacentCharacterPosition, &textBox, nextBoxInDifferentLine, string, leafBoxes);
    399         else if (movingIntoNewBox) {
    400             iter = wordBreakIterator(StringView(textBox.renderer().text()).substring(textBox.start(), textBox.len()));
    401             previouslyVisitedBox = box;
     341        auto& textRun = downcast<LayoutIntegration::TextRunIterator>(run);
     342        unsigned previousRunLength = 0;
     343        bool previousRunInDifferentLine = false;
     344        bool nextRunInDifferentLine = false;
     345        bool movingIntoNewRun = previouslyVisitedRun != run;
     346
     347        if (offsetInRun == textRun->minimumCaretOffset())
     348            iter = wordBreakIteratorForMinOffsetBoundary(adjacentCharacterPosition, textRun, previousRunLength, previousRunInDifferentLine, string);
     349        else if (offsetInRun == textRun->maximumCaretOffset())
     350            iter = wordBreakIteratorForMaxOffsetBoundary(adjacentCharacterPosition, textRun, nextRunInDifferentLine, string);
     351        else if (movingIntoNewRun) {
     352            iter = wordBreakIterator(textRun->text());
     353            previouslyVisitedRun = run;
    402354        }
    403355
     
    406358
    407359        ubrk_first(iter);
    408         int offsetInIterator = offsetInBox - textBox.start() + previousBoxLength;
     360        int offsetInIterator = offsetInRun - textRun->start() + previousRunLength;
    409361
    410362        bool isWordBreak;
    411         bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection;
    412         bool movingBackward = (direction == MoveLeft && box->direction() == TextDirection::LTR) || (direction == MoveRight && box->direction() == TextDirection::RTL);
     363        bool boxHasSameDirectionalityAsBlock = run->direction() == blockDirection;
     364        bool movingBackward = (direction == MoveLeft && run->direction() == TextDirection::LTR) || (direction == MoveRight && run->direction() == TextDirection::RTL);
    413365        if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock)
    414366            || (!skipsSpaceWhenMovingRight && movingBackward)) {
    415             bool logicalStartInRenderer = offsetInBox == static_cast<int>(textBox.start()) && previousBoxInDifferentLine;
     367            bool logicalStartInRenderer = offsetInRun == textRun->start() && previousRunInDifferentLine;
    416368            isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, logicalStartInRenderer);
    417             if (isWordBreak && offsetInBox == box->caretMaxOffset() && nextBoxInDifferentLine)
     369            if (isWordBreak && offsetInRun == run->maximumCaretOffset() && nextRunInDifferentLine)
    418370                isWordBreak = false;
    419371        } else {
    420             bool logicalEndInRenderer = offsetInBox == static_cast<int>(textBox.start() + textBox.len()) && nextBoxInDifferentLine;
     372            bool logicalEndInRenderer = offsetInRun == textRun->end() && nextRunInDifferentLine;
    421373            isWordBreak = islogicalEndOfWord(iter, offsetInIterator, logicalEndInRenderer);
    422             if (isWordBreak && offsetInBox == box->caretMinOffset() && previousBoxInDifferentLine)
     374            if (isWordBreak && offsetInRun == run->minimumCaretOffset() && previousRunInDifferentLine)
    423375                isWordBreak = false;
    424376        }     
     
    1025977
    1026978    if (!line) {
    1027         Position position = previousRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
     979        Position position = previousLineCandidatePosition(node, visiblePosition, editableType);
    1028980        if (position.isNotNull()) {
    1029981            RenderedPosition renderedPosition(position);
     
    10781030        Node* child = node->traverseToChildAt(p.deprecatedEditingOffset());
    10791031        node = child ? child : node->lastDescendant();
    1080         Position position = nextRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
     1032        Position position = nextLineCandidatePosition(node, visiblePosition, editableType);
    10811033        if (position.isNotNull()) {
    10821034            RenderedPosition renderedPosition(position);
Note: See TracChangeset for help on using the changeset viewer.