Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (223698 => 223699)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2017-10-19 18:54:47 UTC (rev 223698)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2017-10-19 18:55:16 UTC (rev 223699)
@@ -185,39 +185,63 @@
return combinedText() ? combinedText()->textCombineFont() : lineStyle().fontCascade();
}
-// FIXME: Share more code with paintSelection().
-LayoutRect InlineTextBox::localSelectionRect(unsigned startPos, unsigned endPos) const
+// FIXME: This function should return the same rectangle as localSelectionRectWithClampedPositions(..., ..., SelectionRectRounding::None),
+// which represents the rectange of the selected text on the page. We need to update all callers to expect this change.
+// See <https://bugs.webkit.org/show_bug.cgi?id=138913> for more details.
+LayoutRect InlineTextBox::localSelectionRect(unsigned startPosition, unsigned endPosition) const
{
- unsigned sPos = clampedOffset(startPos);
- unsigned ePos = clampedOffset(endPos);
+ if (startPosition > endPosition || endPosition < m_start || startPosition > end() + 1)
+ return { };
+ return localSelectionRectWithClampedPositions(clampedOffset(startPosition), clampedOffset(endPosition), SelectionRectRounding::EnclosingIntRect);
+}
- if (sPos >= ePos && !(startPos == endPos && startPos >= start() && startPos <= (start() + len())))
+LayoutRect InlineTextBox::localSelectionRectWithClampedPositions(unsigned clampedStartPosition, unsigned clampedEndPosition, SelectionRectRounding roundingStrategy) const
+{
+ if (clampedStartPosition > clampedEndPosition)
return { };
- LayoutUnit selectionTop = this->selectionTop();
- LayoutUnit selectionHeight = this->selectionHeight();
+ auto selectionTop = root().selectionTopAdjustedForPrecedingBlock();
+ auto selectionBottom = this->selectionBottom();
auto text = this->text();
TextRun textRun = createTextRun(text);
- LayoutRect selectionRect = LayoutRect(LayoutPoint(logicalLeft(), selectionTop), LayoutSize(m_logicalWidth, selectionHeight));
+ // Use same y positioning and height as used for selected text on the page, so that when some or all of this
+ // subrange is selected on the page there are no pieces sticking out.
+ LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop;
+ auto selectionHeight = root().selectionHeightAdjustedForPrecedingBlock();
+ LayoutRect selectionRect { LayoutPoint { logicalLeft(), logicalTop() - deltaY }, LayoutSize { m_logicalWidth, selectionHeight } };
+
// Avoid computing the font width when the entire line box is selected as an optimization.
- if (sPos || ePos != textRun.length())
- lineFont().adjustSelectionRectForText(textRun, selectionRect, sPos, ePos);
- // FIXME: The computation of the snapped selection rect differs from the computation of this rect
- // in paintSelection(). See <https://bugs.webkit.org/show_bug.cgi?id=138913>.
- IntRect snappedSelectionRect = enclosingIntRect(selectionRect);
- LayoutUnit logicalWidth = snappedSelectionRect.width();
- if (snappedSelectionRect.x() > logicalRight())
- logicalWidth = 0;
- else if (snappedSelectionRect.maxX() > logicalRight())
- logicalWidth = logicalRight() - snappedSelectionRect.x();
+ if (clampedStartPosition || clampedEndPosition != textRun.length())
+ lineFont().adjustSelectionRectForText(textRun, selectionRect, clampedStartPosition, clampedEndPosition);
- LayoutPoint topPoint = isHorizontal() ? LayoutPoint(snappedSelectionRect.x(), selectionTop) : LayoutPoint(selectionTop, snappedSelectionRect.x());
- LayoutUnit width = isHorizontal() ? logicalWidth : selectionHeight;
- LayoutUnit height = isHorizontal() ? selectionHeight : logicalWidth;
+ LayoutUnit selectionLeft;
+ LayoutUnit selectionWidth;
+ if (roundingStrategy == SelectionRectRounding::EnclosingIntRect) {
+ auto snappedSelectionRect = enclosingIntRect(selectionRect);
+ selectionLeft = snappedSelectionRect.x();
+ selectionWidth = snappedSelectionRect.width();
+ if (snappedSelectionRect.x() > logicalRight())
+ selectionWidth = 0;
+ else if (snappedSelectionRect.maxX() > logicalRight())
+ selectionWidth = logicalRight() - snappedSelectionRect.x();
+ } else {
+ selectionLeft = selectionRect.x();
+ selectionWidth = selectionRect.width();
+ }
- return LayoutRect(topPoint, LayoutSize(width, height));
+ LayoutPoint location;
+ LayoutSize size;
+ if (isHorizontal()) {
+ location = { selectionLeft, selectionTop };
+ size = { selectionWidth, selectionHeight };
+ } else {
+ location = { selectionTop, selectionLeft };
+ size = { selectionHeight, selectionWidth };
+ }
+
+ return { location, size };
}
void InlineTextBox::deleteLine()
@@ -405,7 +429,7 @@
LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y();
- FloatPoint localPaintOffset(paintOffset);
+ LayoutPoint localPaintOffset { paintOffset };
if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
return;
@@ -472,12 +496,12 @@
// and composition underlines.
if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
if (containsComposition && !useCustomUnderlines)
- paintCompositionBackground(context, boxOrigin);
+ paintCompositionBackground(context, localPaintOffset);
- paintDocumentMarkers(context, boxOrigin, true);
+ paintDocumentMarkers(context, localPaintOffset, true);
if (haveSelection && !useCustomUnderlines)
- paintSelection(context, boxOrigin, selectionPaintStyle.fillColor);
+ paintSelection(context, localPaintOffset, selectionPaintStyle.fillColor);
}
// FIXME: Right now, InlineTextBoxes never call addRelevantUnpaintedObject() even though they might
@@ -579,7 +603,7 @@
}
if (paintInfo.phase == PaintPhaseForeground) {
- paintDocumentMarkers(context, boxOrigin, false);
+ paintDocumentMarkers(context, localPaintOffset, false);
if (useCustomUnderlines)
paintCompositionUnderlines(context, boxOrigin);
@@ -623,7 +647,7 @@
return { clampedOffset(start), clampedOffset(end) };
}
-void InlineTextBox::paintSelection(GraphicsContext& context, const FloatPoint& boxOrigin, const Color& textColor)
+void InlineTextBox::paintSelection(GraphicsContext& context, const LayoutPoint& paintOffset, const Color& textColor)
{
#if ENABLE(TEXT_SELECTION)
if (context.paintingDisabled())
@@ -650,29 +674,19 @@
// Note that if the text is truncated, we let the thing being painted in the truncation
// draw its own highlight.
- auto text = this->text();
- TextRun textRun = createTextRun(text);
+ auto selectionRect = localSelectionRectWithClampedPositions(selectionStart, selectionEnd);
+ selectionRect.moveBy(paintOffset);
- const RootInlineBox& rootBox = root();
- LayoutUnit selectionBottom = rootBox.selectionBottom();
- LayoutUnit selectionTop = rootBox.selectionTopAdjustedForPrecedingBlock();
-
- LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop;
- LayoutUnit selectionHeight = std::max<LayoutUnit>(0, selectionBottom - selectionTop);
-
- LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth, selectionHeight);
- lineFont().adjustSelectionRectForText(textRun, selectionRect, selectionStart, selectionEnd);
-
// FIXME: Support painting combined text.
- context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()), c);
+ context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), isLeftToRightDirection()), c);
#else
UNUSED_PARAM(context);
- UNUSED_PARAM(boxOrigin);
+ UNUSED_PARAM(paintOffset);
UNUSED_PARAM(textColor);
#endif
}
-inline void InlineTextBox::paintTextSubrangeBackground(GraphicsContext& context, const FloatPoint& boxOrigin, const Color& color, unsigned startOffset, unsigned endOffset)
+inline void InlineTextBox::paintTextSubrangeBackground(GraphicsContext& context, const LayoutPoint& paintOffset, const Color& color, unsigned startOffset, unsigned endOffset)
{
startOffset = clampedOffset(startOffset);
endOffset = clampedOffset(endOffset);
@@ -682,30 +696,24 @@
GraphicsContextStateSaver stateSaver { context };
updateGraphicsContext(context, TextPaintStyle { color }); // Don't draw text at all!
- // Use same y positioning and height as for selection, so that when the selection and this subrange are on
- // the same word there are no pieces sticking out.
- LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
- LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, 0, selectionHeight());
+ auto selectionRect = localSelectionRectWithClampedPositions(startOffset, endOffset);
+ selectionRect.moveBy(paintOffset);
- auto text = this->text();
- TextRun textRun = createTextRun(text);
- lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
-
// FIXME: Support painting combined text.
- context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()), color);
+ context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), isLeftToRightDirection()), color);
}
-void InlineTextBox::paintCompositionBackground(GraphicsContext& context, const FloatPoint& boxOrigin)
+void InlineTextBox::paintCompositionBackground(GraphicsContext& context, const LayoutPoint& paintOffset)
{
- paintTextSubrangeBackground(context, boxOrigin, renderer().frame().editor().compositionStart(), renderer().frame().editor().compositionEnd(), Color::compositionFill);
+ paintTextSubrangeBackground(context, paintOffset, renderer().frame().editor().compositionStart(), renderer().frame().editor().compositionEnd(), Color::compositionFill);
}
-void InlineTextBox::paintTextMatchMarker(GraphicsContext& context, const FloatPoint& boxOrigin, const MarkerSubrange& subrange, bool isActiveMatch)
+void InlineTextBox::paintTextMatchMarker(GraphicsContext& context, const LayoutPoint& paintOffset, const MarkerSubrange& subrange, bool isActiveMatch)
{
if (!renderer().frame().editor().markedTextMatchesAreHighlighted())
return;
auto highlightColor = isActiveMatch ? renderer().theme().platformActiveTextSearchHighlightColor() : renderer().theme().platformInactiveTextSearchHighlightColor();
- paintTextSubrangeBackground(context, boxOrigin, highlightColor, subrange.startOffset, subrange.endOffset);
+ paintTextSubrangeBackground(context, paintOffset, highlightColor, subrange.startOffset, subrange.endOffset);
}
static inline void mirrorRTLSegment(float logicalWidth, TextDirection direction, float& start, float width)
@@ -758,7 +766,7 @@
context.concatCTM(rotation(boxRect, Counterclockwise));
}
-void InlineTextBox::paintDocumentMarker(GraphicsContext& context, const FloatPoint& boxOrigin, const MarkerSubrange& subrange)
+void InlineTextBox::paintDocumentMarker(GraphicsContext& context, const LayoutPoint& paintOffset, const MarkerSubrange& subrange)
{
// Never print spelling/grammar markers (5327887)
if (renderer().document().printing())
@@ -767,9 +775,6 @@
if (m_truncation == cFullTruncation)
return;
- float start = 0; // start of line to draw, relative to tx
- float width = m_logicalWidth; // how much line to draw
-
// Determine whether we need to measure text
bool markerSpansWholeBox = true;
if (m_start <= subrange.startOffset)
@@ -779,24 +784,23 @@
if (m_truncation != cNoTruncation)
markerSpansWholeBox = false;
- if (!markerSpansWholeBox) {
+ FloatPoint location;
+ float width;
+ if (markerSpansWholeBox) {
+ location = locationIncludingFlipping();
+ width = m_logicalWidth;
+ } else {
unsigned startPosition = clampedOffset(subrange.startOffset);
unsigned endPosition = clampedOffset(subrange.endOffset);
- // Calculate start & width
- int deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
- int selHeight = selectionHeight();
- FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
- auto text = this->text();
- TextRun run = createTextRun(text);
+ // We round to the nearest enclosing integral rect to avoid truncating the dot decoration on Cocoa platforms.
+ // FIXME: Find a better place to ensure that the Cocoa dots are not truncated.
+ auto selectionRect = localSelectionRectWithClampedPositions(startPosition, endPosition, SelectionRectRounding::EnclosingIntRect);
+ location = selectionRect.location();
+ width = selectionRect.width();
+ }
+ location.moveBy(paintOffset);
- LayoutRect selectionRect = LayoutRect(startPoint, FloatSize(0, selHeight));
- lineFont().adjustSelectionRectForText(run, selectionRect, startPosition, endPosition);
- IntRect markerRect = enclosingIntRect(selectionRect);
- start = markerRect.x() - startPoint.x();
- width = markerRect.width();
- }
-
auto lineStyleForSubrangeType = [] (MarkerSubrange::Type type) {
switch (type) {
case MarkerSubrange::SpellingError:
@@ -836,10 +840,11 @@
underlineOffset = baseline + 2;
}
// FIXME: Support painting combined text.
- context.drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + underlineOffset), width, lineStyleForSubrangeType(subrange.type));
+ location.move(0, underlineOffset);
+ context.drawLineForDocumentMarker(location, width, lineStyleForSubrangeType(subrange.type));
}
-void InlineTextBox::paintDocumentMarkers(GraphicsContext& context, const FloatPoint& boxOrigin, bool background)
+void InlineTextBox::paintDocumentMarkers(GraphicsContext& context, const LayoutPoint& paintOffset, bool background)
{
if (!renderer().textNode())
return;
@@ -933,9 +938,9 @@
for (auto& subrange : subdivide(subranges, OverlapStrategy::Frontmost)) {
if (subrange.type == MarkerSubrange::TextMatch)
- paintTextMatchMarker(context, boxOrigin, subrange, subrange.marker->isActiveMatch());
+ paintTextMatchMarker(context, paintOffset, subrange, subrange.marker->isActiveMatch());
else
- paintDocumentMarker(context, boxOrigin, subrange);
+ paintDocumentMarker(context, paintOffset, subrange);
}
}
Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (223698 => 223699)
--- trunk/Source/WebCore/rendering/InlineTextBox.h 2017-10-19 18:54:47 UTC (rev 223698)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h 2017-10-19 18:55:16 UTC (rev 223699)
@@ -110,7 +110,7 @@
public:
FloatRect calculateBoundaries() const override { return FloatRect(x(), y(), width(), height()); }
- virtual LayoutRect localSelectionRect(unsigned startPos, unsigned endPos) const;
+ virtual LayoutRect localSelectionRect(unsigned startPosition, unsigned endPosition) const;
bool isSelected(unsigned startPosition, unsigned endPosition) const;
std::pair<unsigned, unsigned> selectionStartEnd() const;
@@ -152,18 +152,21 @@
private:
void paintDecoration(GraphicsContext&, const TextRun&, const FloatPoint& textOrigin, const FloatRect& boxRect,
TextDecoration, TextPaintStyle, const ShadowData*, const FloatRect& clipOutRect);
- void paintSelection(GraphicsContext&, const FloatPoint& boxOrigin, const Color&);
+ void paintSelection(GraphicsContext&, const LayoutPoint& paintOffset, const Color&);
- void paintDocumentMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkerSubrange&);
- void paintDocumentMarkers(GraphicsContext&, const FloatPoint& boxOrigin, bool background);
- void paintTextMatchMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkerSubrange&, bool isActiveMatch);
+ void paintDocumentMarker(GraphicsContext&, const LayoutPoint& paintOffset, const MarkerSubrange&);
+ void paintDocumentMarkers(GraphicsContext&, const LayoutPoint& paintOffset, bool background);
+ void paintTextMatchMarker(GraphicsContext&, const LayoutPoint& paintOffset, const MarkerSubrange&, bool isActiveMatch);
- void paintCompositionBackground(GraphicsContext&, const FloatPoint& boxOrigin);
+ void paintCompositionBackground(GraphicsContext&, const LayoutPoint& paintOffset);
void paintCompositionUnderlines(GraphicsContext&, const FloatPoint& boxOrigin) const;
void paintCompositionUnderline(GraphicsContext&, const FloatPoint& boxOrigin, const CompositionUnderline&) const;
- void paintTextSubrangeBackground(GraphicsContext&, const FloatPoint& boxOrigin, const Color&, unsigned startOffset, unsigned endOffset);
+ void paintTextSubrangeBackground(GraphicsContext&, const LayoutPoint& paintOffset, const Color&, unsigned startOffset, unsigned endOffset);
+ enum class SelectionRectRounding { None, EnclosingIntRect };
+ LayoutRect localSelectionRectWithClampedPositions(unsigned clampedStartPosition, unsigned clampedEndPosition, SelectionRectRounding = SelectionRectRounding::None) const;
+
const RenderCombineText* combinedText() const;
const FontCascade& lineFont() const;