⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 285938 in webkit


Ignore:
Timestamp:
Nov 17, 2021, 10:51:16 AM (5 years ago)
Author:
Antti Koivisto
Message:

InlineIterator::TextBox::offsetForPosition and positionForOffset should be layout path independent
https://bugs.webkit.org/show_bug.cgi?id=233259

Reviewed by Alan Bujtas.

Remove imperfectly duplicated code.

This also fixes editing/mac/input/caret-primary-bidi.html with IFC BiDi.

  • layout/integration/InlineIteratorBoxLegacyPath.h:

(WebCore::InlineIterator::BoxLegacyPath::createTextRun const):
(WebCore::InlineIterator::BoxLegacyPath::offsetForPosition const): Deleted.
(WebCore::InlineIterator::BoxLegacyPath::positionForOffset const): Deleted.

  • layout/integration/InlineIteratorBoxModernPath.h:

(WebCore::InlineIterator::BoxModernPath::createTextRun const):
(WebCore::InlineIterator::BoxModernPath::offsetForPosition const): Deleted.
(WebCore::InlineIterator::BoxModernPath::positionForOffset const): Deleted.

  • layout/integration/InlineIteratorTextBox.cpp:

(WebCore::InlineIterator::TextBox::offsetForPosition const):
(WebCore::InlineIterator::TextBox::positionForOffset const):

  • layout/integration/InlineIteratorTextBox.h:

(WebCore::InlineIterator::TextBox::createTextRun const):
(WebCore::InlineIterator::TextBox::offsetForPosition const): Deleted.
(WebCore::InlineIterator::TextBox::positionForOffset const): Deleted.

  • rendering/LegacyInlineTextBox.cpp:

(WebCore::LegacyInlineTextBox::placeEllipsisBox):
(WebCore::LegacyInlineTextBox::offsetForPosition const): Deleted.
(WebCore::LegacyInlineTextBox::positionForOffset const): Deleted.

  • rendering/LegacyInlineTextBox.h:
  • rendering/svg/SVGInlineTextBox.cpp:

(WebCore::SVGInlineTextBox::offsetForPosition const): Deleted.
(WebCore::SVGInlineTextBox::positionForOffset const): Deleted.

  • rendering/svg/SVGInlineTextBox.h:
Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r285936 r285938  
     12021-11-17  Antti Koivisto  <antti@apple.com>
     2
     3        InlineIterator::TextBox::offsetForPosition and positionForOffset should be layout path independent
     4        https://bugs.webkit.org/show_bug.cgi?id=233259
     5
     6        Reviewed by Alan Bujtas.
     7
     8        Remove imperfectly duplicated code.
     9
     10        This also fixes editing/mac/input/caret-primary-bidi.html with IFC BiDi.
     11
     12        * layout/integration/InlineIteratorBoxLegacyPath.h:
     13        (WebCore::InlineIterator::BoxLegacyPath::createTextRun const):
     14        (WebCore::InlineIterator::BoxLegacyPath::offsetForPosition const): Deleted.
     15        (WebCore::InlineIterator::BoxLegacyPath::positionForOffset const): Deleted.
     16        * layout/integration/InlineIteratorBoxModernPath.h:
     17        (WebCore::InlineIterator::BoxModernPath::createTextRun const):
     18        (WebCore::InlineIterator::BoxModernPath::offsetForPosition const): Deleted.
     19        (WebCore::InlineIterator::BoxModernPath::positionForOffset const): Deleted.
     20        * layout/integration/InlineIteratorTextBox.cpp:
     21        (WebCore::InlineIterator::TextBox::offsetForPosition const):
     22        (WebCore::InlineIterator::TextBox::positionForOffset const):
     23        * layout/integration/InlineIteratorTextBox.h:
     24        (WebCore::InlineIterator::TextBox::createTextRun const):
     25        (WebCore::InlineIterator::TextBox::offsetForPosition const): Deleted.
     26        (WebCore::InlineIterator::TextBox::positionForOffset const): Deleted.
     27        * rendering/LegacyInlineTextBox.cpp:
     28        (WebCore::LegacyInlineTextBox::placeEllipsisBox):
     29        (WebCore::LegacyInlineTextBox::offsetForPosition const): Deleted.
     30        (WebCore::LegacyInlineTextBox::positionForOffset const): Deleted.
     31        * rendering/LegacyInlineTextBox.h:
     32        * rendering/svg/SVGInlineTextBox.cpp:
     33        (WebCore::SVGInlineTextBox::offsetForPosition const): Deleted.
     34        (WebCore::SVGInlineTextBox::positionForOffset const): Deleted.
     35        * rendering/svg/SVGInlineTextBox.h:
     36
    1372021-11-17  Dean Jackson  <dino@apple.com>
    238
  • trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h

    r284334 r285938  
    3636namespace InlineIterator {
    3737
     38enum class CreateTextRunMode { Painting, Editing };
     39
    3840class BoxLegacyPath {
    3941public:
     
    6365    unsigned length() const { return inlineTextBox()->len(); }
    6466
    65     unsigned offsetForPosition(float x) const { return inlineTextBox()->offsetForPosition(x); }
    66     float positionForOffset(unsigned offset) const { return inlineTextBox()->positionForOffset(offset); }
    67 
    6867    TextBoxSelectableRange selectableRange() const { return inlineTextBox()->selectableRange(); }
    6968
    70     TextRun createTextRun() const { return inlineTextBox()->createTextRun(); }
     69    TextRun createTextRun(CreateTextRunMode mode) const
     70    {
     71        bool ignoreCombinedText = mode == CreateTextRunMode::Editing;
     72        bool ignoreHyphen = mode == CreateTextRunMode::Editing;
     73        return inlineTextBox()->createTextRun(ignoreCombinedText, ignoreHyphen);
     74    }
    7175
    7276    const RenderObject& renderer() const
  • trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h

    r285171 r285938  
    7171    unsigned length() const { return box().text()->length(); }
    7272
    73     // FIXME: Make a shared generic version of this.
    74     inline unsigned offsetForPosition(float x) const
    75     {
    76         if (isLineBreak())
    77             return 0;
    78         auto rect = this->rect();
    79         auto localX = x - rect.x();
    80         if (localX > rect.width())
    81             return length();
    82         if (localX < 0)
    83             return 0;
    84 
    85         bool includePartialGlyphs = true;
    86         return box().style().fontCascade().offsetForPosition(createTextRun(HyphenMode::Ignore), localX, includePartialGlyphs);
    87     }
    88 
    89     // FIXME: Make a shared generic version of this.
    90     float positionForOffset(unsigned offset) const
    91     {
    92         ASSERT(offset >= start());
    93         ASSERT(offset <= end());
    94 
    95         if (isLineBreak())
    96             return rect().x();
    97 
    98         auto endOffset = selectableRange().clamp(offset);
    99 
    100         LayoutRect selectionRect = LayoutRect(rect().x(), 0, 0, 0);
    101         TextRun textRun = createTextRun(HyphenMode::Ignore);
    102         box().style().fontCascade().adjustSelectionRectForText(textRun, selectionRect, 0, endOffset);
    103         return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
    104     }
    105 
    10673    TextBoxSelectableRange selectableRange() const
    10774    {
     
    11481    }
    11582
    116     TextRun createTextRun() const
    117     {
    118         return createTextRun(HyphenMode::Include);
     83    TextRun createTextRun(CreateTextRunMode mode) const
     84    {
     85        auto& style = box().style();
     86        auto expansion = box().expansion();
     87        auto rect = this->rect();
     88        auto xPos = rect.x() - (line().lineBoxLeft() + line().contentLeft());
     89
     90        auto textForRun = [&] {
     91            if (mode == CreateTextRunMode::Editing || !hasHyphen())
     92                return text().toStringWithoutCopying();
     93
     94            return makeString(text(), style.hyphenString());
     95        }();
     96
     97        bool directionalOverride = dirOverride() || style.rtlOrdering() == Order::Visual;
     98        bool characterScanForCodePath = !renderText().canUseSimpleFontCodePath();
     99        TextRun textRun { textForRun, xPos, expansion.horizontalExpansion, expansion.behavior, direction(), directionalOverride, characterScanForCodePath };
     100        textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
     101        return textRun;
    119102    };
    120103
     
    275258    const LayoutIntegration::Line& line() const { return m_inlineContent->lineForBox(box()); }
    276259
    277     enum class HyphenMode { Include, Ignore };
    278     TextRun createTextRun(HyphenMode hyphenMode) const
    279     {
    280         auto& style = box().style();
    281         auto expansion = box().expansion();
    282         auto rect = this->rect();
    283         auto xPos = rect.x() - (line().lineBoxLeft() + line().contentLeft());
    284 
    285         auto textForRun = [&] {
    286             if (hyphenMode == HyphenMode::Ignore || !hasHyphen())
    287                 return text().toStringWithoutCopying();
    288 
    289             return makeString(text(), style.hyphenString());
    290         }();
    291 
    292         bool directionalOverride = dirOverride() || style.rtlOrdering() == Order::Visual;
    293         bool characterScanForCodePath = !renderText().canUseSimpleFontCodePath();
    294         TextRun textRun { textForRun, xPos, expansion.horizontalExpansion, expansion.behavior, direction(), directionalOverride, characterScanForCodePath };
    295         textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
    296         return textRun;
    297     };
    298 
    299260    const RenderText& renderText() const { return downcast<RenderText>(renderer()); }
    300261    TextDirection direction() const { return bidiLevel() % 2 ? TextDirection::RTL : TextDirection::LTR; }
  • trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp

    r284269 r285938  
    5656
    5757    return snappedSelectionRect(selectionRect, logicalRight(), selectionTop, selectionHeight, isHorizontal());
     58}
     59
     60unsigned TextBox::offsetForPosition(float x, bool includePartialGlyphs) const
     61{
     62    if (isLineBreak())
     63        return 0;
     64    if (x - logicalLeft() > logicalWidth())
     65        return isLeftToRightDirection() ? length() : 0;
     66    if (x - logicalLeft() < 0)
     67        return isLeftToRightDirection() ? 0 : length();
     68    return fontCascade().offsetForPosition(createTextRun(CreateTextRunMode::Editing), x - logicalLeft(), includePartialGlyphs);
     69}
     70
     71float TextBox::positionForOffset(unsigned offset) const
     72{
     73    ASSERT(offset >= start());
     74    ASSERT(offset <= end());
     75
     76    if (isLineBreak())
     77        return logicalLeft();
     78
     79    auto [startOffset, endOffset] = [&] {
     80        if (direction() == TextDirection::RTL)
     81            return std::pair { selectableRange().clamp(offset), length() };
     82        return std::pair { 0u, selectableRange().clamp(offset) };
     83    }();
     84
     85    auto selectionRect = LayoutRect(logicalLeft(), 0, 0, 0);
     86   
     87    auto textRun = createTextRun(CreateTextRunMode::Editing);
     88    fontCascade().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
     89    return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
    5890}
    5991
  • trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h

    r284269 r285938  
    4444    unsigned length() const;
    4545
    46     unsigned offsetForPosition(float x) const;
     46    unsigned offsetForPosition(float x, bool includePartialGlyphs = true) const;
    4747    float positionForOffset(unsigned) const;
    4848
     
    5353    const FontCascade& fontCascade() const;
    5454
    55     TextRun createTextRun() const;
     55    TextRun createTextRun(CreateTextRunMode = CreateTextRunMode::Painting) const;
    5656
    5757    const RenderText& renderer() const { return downcast<RenderText>(Box::renderer()); }
     
    148148}
    149149
    150 inline unsigned TextBox::offsetForPosition(float x) const
    151 {
    152     return WTF::switchOn(m_pathVariant, [&](auto& path) {
    153         return path.offsetForPosition(x);
    154     });
    155 }
    156 
    157 inline float TextBox::positionForOffset(unsigned offset) const
    158 {
    159     return WTF::switchOn(m_pathVariant, [&](auto& path) {
    160         return path.positionForOffset(offset);
    161     });
    162 }
    163 
    164150inline TextBoxSelectableRange TextBox::selectableRange() const
    165151{
     
    169155}
    170156
    171 inline TextRun TextBox::createTextRun() const
     157inline TextRun TextBox::createTextRun(CreateTextRunMode mode) const
    172158{
    173159    return WTF::switchOn(m_pathVariant, [&](auto& path) {
    174         return path.createTextRun();
     160        return path.createTextRun(mode);
    175161    });
    176162}
  • trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp

    r284857 r285938  
    3535#include "Frame.h"
    3636#include "GraphicsContext.h"
    37 
    3837#include "HighlightData.h"
    3938#include "HitTestResult.h"
    4039#include "ImageBuffer.h"
     40#include "InlineIteratorTextBox.h"
    4141#include "InlineTextBoxStyle.h"
    4242#include "LegacyEllipsisBox.h"
     
    269269        }
    270270
    271         int offset = offsetForPosition(ellipsisX, false);
     271        int offset = InlineIterator::textBoxFor(this)->offsetForPosition(ellipsisX, false);
    272272        if (!offset) {
    273273            // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
     
    451451        return 0;
    452452    return logicalLeft() - root().logicalLeft();
    453 }
    454 
    455 int LegacyInlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs) const
    456 {
    457     if (isLineBreak())
    458         return 0;
    459     if (lineOffset - logicalLeft() > logicalWidth())
    460         return isLeftToRightDirection() ? len() : 0;
    461     if (lineOffset - logicalLeft() < 0)
    462         return isLeftToRightDirection() ? 0 : len();
    463     bool ignoreCombinedText = true;
    464     bool ignoreHyphen = true;
    465     return lineFont().offsetForPosition(createTextRun(ignoreCombinedText, ignoreHyphen), lineOffset - logicalLeft(), includePartialGlyphs);
    466 }
    467 
    468 float LegacyInlineTextBox::positionForOffset(unsigned offset) const
    469 {
    470     ASSERT(offset >= m_start);
    471     ASSERT(offset <= m_start + len());
    472 
    473     if (isLineBreak())
    474         return logicalLeft();
    475 
    476     unsigned startOffset;
    477     unsigned endOffset;
    478     if (isLeftToRightDirection()) {
    479         startOffset = 0;
    480         endOffset = selectableRange().clamp(offset);
    481     } else {
    482         startOffset = selectableRange().clamp(offset);
    483         endOffset = m_len;
    484     }
    485 
    486     // FIXME: Do we need to add rightBearing here?
    487     LayoutRect selectionRect = LayoutRect(logicalLeft(), 0, 0, 0);
    488     bool ignoreCombinedText = true;
    489     bool ignoreHyphen = true;
    490     TextRun textRun = createTextRun(ignoreCombinedText, ignoreHyphen);
    491     lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
    492     return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
    493453}
    494454
  • trunk/Source/WebCore/rendering/LegacyInlineTextBox.h

    r284112 r285938  
    147147
    148148public:
    149     virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
    150     virtual float positionForOffset(unsigned offset) const;
    151 
    152149    bool hasMarkers() const;
    153150
  • trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp

    r285904 r285938  
    7979}
    8080
    81 int SVGInlineTextBox::offsetForPosition(float, bool) const
    82 {
    83     // SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
    84     // vertical text selection, inline boxes spanning multiple lines (contrary to HTML, etc.)
    85     ASSERT_NOT_REACHED();
    86     return 0;
    87 }
    88 
    8981int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
    9082{
     
    10294
    10395    return fragment.characterOffset - start() + renderer().scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
    104 }
    105 
    106 float SVGInlineTextBox::positionForOffset(unsigned) const
    107 {
    108     // SVG doesn't use the offset <-> position selection system.
    109     ASSERT_NOT_REACHED();
    110     return 0;
    11196}
    11297
  • trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.h

    r285904 r285938  
    4444    int selectionTop() { return top(); }
    4545    int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); }
    46     int offsetForPosition(float x, bool includePartialGlyphs = true) const override;
    47     float positionForOffset(unsigned offset) const override;
    4846
    4947    void paintSelectionBackground(PaintInfo&);
Note: See TracChangeset for help on using the changeset viewer.