Diff
Modified: trunk/Source/WebCore/ChangeLog (285937 => 285938)
--- trunk/Source/WebCore/ChangeLog 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/ChangeLog 2021-11-17 18:51:16 UTC (rev 285938)
@@ -1,3 +1,39 @@
+2021-11-17 Antti Koivisto <[email protected]>
+
+ 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:
+
2021-11-17 Dean Jackson <[email protected]>
Add ModelDocument for directly showing content that can be handled by <model>
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h (285937 => 285938)
--- trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h 2021-11-17 18:51:16 UTC (rev 285938)
@@ -35,6 +35,8 @@
namespace WebCore {
namespace InlineIterator {
+enum class CreateTextRunMode { Painting, Editing };
+
class BoxLegacyPath {
public:
BoxLegacyPath(const LegacyInlineBox* inlineBox)
@@ -62,12 +64,14 @@
unsigned end() const { return inlineTextBox()->end(); }
unsigned length() const { return inlineTextBox()->len(); }
- unsigned offsetForPosition(float x) const { return inlineTextBox()->offsetForPosition(x); }
- float positionForOffset(unsigned offset) const { return inlineTextBox()->positionForOffset(offset); }
-
TextBoxSelectableRange selectableRange() const { return inlineTextBox()->selectableRange(); }
- TextRun createTextRun() const { return inlineTextBox()->createTextRun(); }
+ TextRun createTextRun(CreateTextRunMode mode) const
+ {
+ bool ignoreCombinedText = mode == CreateTextRunMode::Editing;
+ bool ignoreHyphen = mode == CreateTextRunMode::Editing;
+ return inlineTextBox()->createTextRun(ignoreCombinedText, ignoreHyphen);
+ }
const RenderObject& renderer() const
{
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h (285937 => 285938)
--- trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-11-17 18:51:16 UTC (rev 285938)
@@ -70,39 +70,6 @@
unsigned end() const { return box().text()->end(); }
unsigned length() const { return box().text()->length(); }
- // FIXME: Make a shared generic version of this.
- inline unsigned offsetForPosition(float x) const
- {
- if (isLineBreak())
- return 0;
- auto rect = this->rect();
- auto localX = x - rect.x();
- if (localX > rect.width())
- return length();
- if (localX < 0)
- return 0;
-
- bool includePartialGlyphs = true;
- return box().style().fontCascade().offsetForPosition(createTextRun(HyphenMode::Ignore), localX, includePartialGlyphs);
- }
-
- // FIXME: Make a shared generic version of this.
- float positionForOffset(unsigned offset) const
- {
- ASSERT(offset >= start());
- ASSERT(offset <= end());
-
- if (isLineBreak())
- return rect().x();
-
- auto endOffset = selectableRange().clamp(offset);
-
- LayoutRect selectionRect = LayoutRect(rect().x(), 0, 0, 0);
- TextRun textRun = createTextRun(HyphenMode::Ignore);
- box().style().fontCascade().adjustSelectionRectForText(textRun, selectionRect, 0, endOffset);
- return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
- }
-
TextBoxSelectableRange selectableRange() const
{
return {
@@ -113,9 +80,25 @@
};
}
- TextRun createTextRun() const
+ TextRun createTextRun(CreateTextRunMode mode) const
{
- return createTextRun(HyphenMode::Include);
+ auto& style = box().style();
+ auto expansion = box().expansion();
+ auto rect = this->rect();
+ auto xPos = rect.x() - (line().lineBoxLeft() + line().contentLeft());
+
+ auto textForRun = [&] {
+ if (mode == CreateTextRunMode::Editing || !hasHyphen())
+ return text().toStringWithoutCopying();
+
+ return makeString(text(), style.hyphenString());
+ }();
+
+ bool directionalOverride = dirOverride() || style.rtlOrdering() == Order::Visual;
+ bool characterScanForCodePath = !renderText().canUseSimpleFontCodePath();
+ TextRun textRun { textForRun, xPos, expansion.horizontalExpansion, expansion.behavior, direction(), directionalOverride, characterScanForCodePath };
+ textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
+ return textRun;
};
const RenderObject& renderer() const
@@ -274,28 +257,6 @@
const LayoutIntegration::InlineContent::Boxes& boxes() const { return m_inlineContent->boxes; }
const LayoutIntegration::Line& line() const { return m_inlineContent->lineForBox(box()); }
- enum class HyphenMode { Include, Ignore };
- TextRun createTextRun(HyphenMode hyphenMode) const
- {
- auto& style = box().style();
- auto expansion = box().expansion();
- auto rect = this->rect();
- auto xPos = rect.x() - (line().lineBoxLeft() + line().contentLeft());
-
- auto textForRun = [&] {
- if (hyphenMode == HyphenMode::Ignore || !hasHyphen())
- return text().toStringWithoutCopying();
-
- return makeString(text(), style.hyphenString());
- }();
-
- bool directionalOverride = dirOverride() || style.rtlOrdering() == Order::Visual;
- bool characterScanForCodePath = !renderText().canUseSimpleFontCodePath();
- TextRun textRun { textForRun, xPos, expansion.horizontalExpansion, expansion.behavior, direction(), directionalOverride, characterScanForCodePath };
- textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
- return textRun;
- };
-
const RenderText& renderText() const { return downcast<RenderText>(renderer()); }
TextDirection direction() const { return bidiLevel() % 2 ? TextDirection::RTL : TextDirection::LTR; }
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp (285937 => 285938)
--- trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp 2021-11-17 18:51:16 UTC (rev 285938)
@@ -57,6 +57,38 @@
return snappedSelectionRect(selectionRect, logicalRight(), selectionTop, selectionHeight, isHorizontal());
}
+unsigned TextBox::offsetForPosition(float x, bool includePartialGlyphs) const
+{
+ if (isLineBreak())
+ return 0;
+ if (x - logicalLeft() > logicalWidth())
+ return isLeftToRightDirection() ? length() : 0;
+ if (x - logicalLeft() < 0)
+ return isLeftToRightDirection() ? 0 : length();
+ return fontCascade().offsetForPosition(createTextRun(CreateTextRunMode::Editing), x - logicalLeft(), includePartialGlyphs);
+}
+
+float TextBox::positionForOffset(unsigned offset) const
+{
+ ASSERT(offset >= start());
+ ASSERT(offset <= end());
+
+ if (isLineBreak())
+ return logicalLeft();
+
+ auto [startOffset, endOffset] = [&] {
+ if (direction() == TextDirection::RTL)
+ return std::pair { selectableRange().clamp(offset), length() };
+ return std::pair { 0u, selectableRange().clamp(offset) };
+ }();
+
+ auto selectionRect = LayoutRect(logicalLeft(), 0, 0, 0);
+
+ auto textRun = createTextRun(CreateTextRunMode::Editing);
+ fontCascade().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
+ return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
+}
+
bool TextBox::isCombinedText() const
{
auto& renderer = this->renderer();
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h (285937 => 285938)
--- trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h 2021-11-17 18:51:16 UTC (rev 285938)
@@ -43,7 +43,7 @@
unsigned end() const;
unsigned length() const;
- unsigned offsetForPosition(float x) const;
+ unsigned offsetForPosition(float x, bool includePartialGlyphs = true) const;
float positionForOffset(unsigned) const;
TextBoxSelectableRange selectableRange() const;
@@ -52,7 +52,7 @@
bool isCombinedText() const;
const FontCascade& fontCascade() const;
- TextRun createTextRun() const;
+ TextRun createTextRun(CreateTextRunMode = CreateTextRunMode::Painting) const;
const RenderText& renderer() const { return downcast<RenderText>(Box::renderer()); }
@@ -147,20 +147,6 @@
});
}
-inline unsigned TextBox::offsetForPosition(float x) const
-{
- return WTF::switchOn(m_pathVariant, [&](auto& path) {
- return path.offsetForPosition(x);
- });
-}
-
-inline float TextBox::positionForOffset(unsigned offset) const
-{
- return WTF::switchOn(m_pathVariant, [&](auto& path) {
- return path.positionForOffset(offset);
- });
-}
-
inline TextBoxSelectableRange TextBox::selectableRange() const
{
return WTF::switchOn(m_pathVariant, [&](auto& path) {
@@ -168,10 +154,10 @@
});
}
-inline TextRun TextBox::createTextRun() const
+inline TextRun TextBox::createTextRun(CreateTextRunMode mode) const
{
return WTF::switchOn(m_pathVariant, [&](auto& path) {
- return path.createTextRun();
+ return path.createTextRun(mode);
});
}
Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp (285937 => 285938)
--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp 2021-11-17 18:51:16 UTC (rev 285938)
@@ -34,10 +34,10 @@
#include "FloatRoundedRect.h"
#include "Frame.h"
#include "GraphicsContext.h"
-
#include "HighlightData.h"
#include "HitTestResult.h"
#include "ImageBuffer.h"
+#include "InlineIteratorTextBox.h"
#include "InlineTextBoxStyle.h"
#include "LegacyEllipsisBox.h"
#include "Page.h"
@@ -268,7 +268,7 @@
ellipsisX = ltr ? left() + visibleBoxWidth : right() - visibleBoxWidth;
}
- int offset = offsetForPosition(ellipsisX, false);
+ int offset = InlineIterator::textBoxFor(this)->offsetForPosition(ellipsisX, false);
if (!offset) {
// No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
// and the ellipsis edge.
@@ -452,46 +452,6 @@
return logicalLeft() - root().logicalLeft();
}
-int LegacyInlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs) const
-{
- if (isLineBreak())
- return 0;
- if (lineOffset - logicalLeft() > logicalWidth())
- return isLeftToRightDirection() ? len() : 0;
- if (lineOffset - logicalLeft() < 0)
- return isLeftToRightDirection() ? 0 : len();
- bool ignoreCombinedText = true;
- bool ignoreHyphen = true;
- return lineFont().offsetForPosition(createTextRun(ignoreCombinedText, ignoreHyphen), lineOffset - logicalLeft(), includePartialGlyphs);
-}
-
-float LegacyInlineTextBox::positionForOffset(unsigned offset) const
-{
- ASSERT(offset >= m_start);
- ASSERT(offset <= m_start + len());
-
- if (isLineBreak())
- return logicalLeft();
-
- unsigned startOffset;
- unsigned endOffset;
- if (isLeftToRightDirection()) {
- startOffset = 0;
- endOffset = selectableRange().clamp(offset);
- } else {
- startOffset = selectableRange().clamp(offset);
- endOffset = m_len;
- }
-
- // FIXME: Do we need to add rightBearing here?
- LayoutRect selectionRect = LayoutRect(logicalLeft(), 0, 0, 0);
- bool ignoreCombinedText = true;
- bool ignoreHyphen = true;
- TextRun textRun = createTextRun(ignoreCombinedText, ignoreHyphen);
- lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
- return snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()).maxX();
-}
-
TextRun LegacyInlineTextBox::createTextRun(bool ignoreCombinedText, bool ignoreHyphen) const
{
const auto& style = lineStyle();
Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.h (285937 => 285938)
--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-11-17 18:51:16 UTC (rev 285938)
@@ -146,9 +146,6 @@
float textPos() const; // returns the x position relative to the left start of the text line.
public:
- virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
- virtual float positionForOffset(unsigned offset) const;
-
bool hasMarkers() const;
private:
Modified: trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp (285937 => 285938)
--- trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp 2021-11-17 18:51:16 UTC (rev 285938)
@@ -78,14 +78,6 @@
nextBox->dirtyOwnLineBoxes();
}
-int SVGInlineTextBox::offsetForPosition(float, bool) const
-{
- // SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
- // vertical text selection, inline boxes spanning multiple lines (contrary to HTML, etc.)
- ASSERT_NOT_REACHED();
- return 0;
-}
-
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
{
float scalingFactor = renderer().scalingFactor();
@@ -103,13 +95,6 @@
return fragment.characterOffset - start() + renderer().scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
-float SVGInlineTextBox::positionForOffset(unsigned) const
-{
- // SVG doesn't use the offset <-> position selection system.
- ASSERT_NOT_REACHED();
- return 0;
-}
-
FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, unsigned startPosition, unsigned endPosition, const RenderStyle& style) const
{
ASSERT_WITH_SECURITY_IMPLICATION(startPosition < endPosition);
Modified: trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.h (285937 => 285938)
--- trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.h 2021-11-17 18:50:01 UTC (rev 285937)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.h 2021-11-17 18:51:16 UTC (rev 285938)
@@ -43,8 +43,6 @@
int selectionTop() { return top(); }
int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); }
- int offsetForPosition(float x, bool includePartialGlyphs = true) const override;
- float positionForOffset(unsigned offset) const override;
void paintSelectionBackground(PaintInfo&);
void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;