Changeset 223699 in webkit
- Timestamp:
- Oct 19, 2017 11:55:16 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r223697 r223699 1 2017-10-19 Daniel Bates <dabates@apple.com> 2 3 Share logic in InlineTextBox to compute selection rect 4 https://bugs.webkit.org/show_bug.cgi?id=178232 5 <rdar://problem/34963452> 6 7 Reviewed by Zalan Bujtas. 8 9 Currently each paint routine in InlineTextBox duplicates similar code to compute the selection 10 rect it will paint. This change consolidates all the duplication into localSelectionRectWithClampedPositions() 11 and writes all of the paint operations, except for paintCompositionUnderline(), in terms of it. 12 We will write paintCompositionUnderline() in terms of localSelectionRectWithClampedPositions() 13 in a subsequent patch. 14 15 We also write localSelectionRect() in terms of localSelectionRectWithClampedPositions(). Ideally 16 we would have one way to compute the selection rect. However, localSelectionRect() and paintDocumentMarker() 17 currently expect the enclosing integral rectangle of the selection rectangle. The function 18 paintDocumentMarker() needs the enclosing integral rectangle to avoid truncating the dot pattern 19 drawn under marked words (e.g. a spelling error) on Cocoa platforms. With regards to localSelectionRect() 20 we should look to have it return the actual selection rectangle. See <https://bugs.webkit.org/show_bug.cgi?id=138913> 21 for more details. 22 23 * rendering/InlineTextBox.cpp: 24 (WebCore::InlineTextBox::localSelectionRect const): Move logic in common with paintSelection() into 25 localSelectionRectWithClampedPositions() and modified code to use it. 26 (WebCore::InlineTextBox::localSelectionRectWithClampedPositions const): Added. 27 (WebCore::InlineTextBox::paint): Store the local paint offset as a LayoutPoint as it is the canonical 28 data type for representing an offset when painting. Pass the local paint offset instead of the analagous boxOrigin value. 29 (WebCore::InlineTextBox::paintSelection): Write in terms of localSelectionRectWithClampedPositions(). 30 (WebCore::InlineTextBox::paintTextSubrangeBackground): Ditto. 31 (WebCore::InlineTextBox::paintCompositionBackground): Ditto. 32 (WebCore::InlineTextBox::paintTextMatchMarker): Ditto. 33 (WebCore::InlineTextBox::paintDocumentMarker): Ditto. 34 (WebCore::InlineTextBox::paintDocumentMarkers): Pass paint offset instead of the analogous boxOrigin value. 35 * rendering/InlineTextBox.h: 36 1 37 2017-10-19 Daniel Bates <dabates@apple.com> 2 38 -
trunk/Source/WebCore/rendering/InlineTextBox.cpp
r223553 r223699 186 186 } 187 187 188 // FIXME: Share more code with paintSelection(). 189 LayoutRect InlineTextBox::localSelectionRect(unsigned startPos, unsigned endPos) const 190 { 191 unsigned sPos = clampedOffset(startPos); 192 unsigned ePos = clampedOffset(endPos); 193 194 if (sPos >= ePos && !(startPos == endPos && startPos >= start() && startPos <= (start() + len()))) 188 // FIXME: This function should return the same rectangle as localSelectionRectWithClampedPositions(..., ..., SelectionRectRounding::None), 189 // which represents the rectange of the selected text on the page. We need to update all callers to expect this change. 190 // See <https://bugs.webkit.org/show_bug.cgi?id=138913> for more details. 191 LayoutRect InlineTextBox::localSelectionRect(unsigned startPosition, unsigned endPosition) const 192 { 193 if (startPosition > endPosition || endPosition < m_start || startPosition > end() + 1) 195 194 return { }; 196 197 LayoutUnit selectionTop = this->selectionTop(); 198 LayoutUnit selectionHeight = this->selectionHeight(); 195 return localSelectionRectWithClampedPositions(clampedOffset(startPosition), clampedOffset(endPosition), SelectionRectRounding::EnclosingIntRect); 196 } 197 198 LayoutRect InlineTextBox::localSelectionRectWithClampedPositions(unsigned clampedStartPosition, unsigned clampedEndPosition, SelectionRectRounding roundingStrategy) const 199 { 200 if (clampedStartPosition > clampedEndPosition) 201 return { }; 202 203 auto selectionTop = root().selectionTopAdjustedForPrecedingBlock(); 204 auto selectionBottom = this->selectionBottom(); 199 205 200 206 auto text = this->text(); 201 207 TextRun textRun = createTextRun(text); 202 208 203 LayoutRect selectionRect = LayoutRect(LayoutPoint(logicalLeft(), selectionTop), LayoutSize(m_logicalWidth, selectionHeight)); 209 // Use same y positioning and height as used for selected text on the page, so that when some or all of this 210 // subrange is selected on the page there are no pieces sticking out. 211 LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop; 212 auto selectionHeight = root().selectionHeightAdjustedForPrecedingBlock(); 213 LayoutRect selectionRect { LayoutPoint { logicalLeft(), logicalTop() - deltaY }, LayoutSize { m_logicalWidth, selectionHeight } }; 214 204 215 // Avoid computing the font width when the entire line box is selected as an optimization. 205 if (sPos || ePos != textRun.length()) 206 lineFont().adjustSelectionRectForText(textRun, selectionRect, sPos, ePos); 207 // FIXME: The computation of the snapped selection rect differs from the computation of this rect 208 // in paintSelection(). See <https://bugs.webkit.org/show_bug.cgi?id=138913>. 209 IntRect snappedSelectionRect = enclosingIntRect(selectionRect); 210 LayoutUnit logicalWidth = snappedSelectionRect.width(); 211 if (snappedSelectionRect.x() > logicalRight()) 212 logicalWidth = 0; 213 else if (snappedSelectionRect.maxX() > logicalRight()) 214 logicalWidth = logicalRight() - snappedSelectionRect.x(); 215 216 LayoutPoint topPoint = isHorizontal() ? LayoutPoint(snappedSelectionRect.x(), selectionTop) : LayoutPoint(selectionTop, snappedSelectionRect.x()); 217 LayoutUnit width = isHorizontal() ? logicalWidth : selectionHeight; 218 LayoutUnit height = isHorizontal() ? selectionHeight : logicalWidth; 219 220 return LayoutRect(topPoint, LayoutSize(width, height)); 216 if (clampedStartPosition || clampedEndPosition != textRun.length()) 217 lineFont().adjustSelectionRectForText(textRun, selectionRect, clampedStartPosition, clampedEndPosition); 218 219 LayoutUnit selectionLeft; 220 LayoutUnit selectionWidth; 221 if (roundingStrategy == SelectionRectRounding::EnclosingIntRect) { 222 auto snappedSelectionRect = enclosingIntRect(selectionRect); 223 selectionLeft = snappedSelectionRect.x(); 224 selectionWidth = snappedSelectionRect.width(); 225 if (snappedSelectionRect.x() > logicalRight()) 226 selectionWidth = 0; 227 else if (snappedSelectionRect.maxX() > logicalRight()) 228 selectionWidth = logicalRight() - snappedSelectionRect.x(); 229 } else { 230 selectionLeft = selectionRect.x(); 231 selectionWidth = selectionRect.width(); 232 } 233 234 LayoutPoint location; 235 LayoutSize size; 236 if (isHorizontal()) { 237 location = { selectionLeft, selectionTop }; 238 size = { selectionWidth, selectionHeight }; 239 } else { 240 location = { selectionTop, selectionLeft }; 241 size = { selectionHeight, selectionWidth }; 242 } 243 244 return { location, size }; 221 245 } 222 246 … … 406 430 LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y(); 407 431 408 FloatPoint localPaintOffset(paintOffset);432 LayoutPoint localPaintOffset { paintOffset }; 409 433 410 434 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) … … 473 497 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) { 474 498 if (containsComposition && !useCustomUnderlines) 475 paintCompositionBackground(context, boxOrigin);476 477 paintDocumentMarkers(context, boxOrigin, true);499 paintCompositionBackground(context, localPaintOffset); 500 501 paintDocumentMarkers(context, localPaintOffset, true); 478 502 479 503 if (haveSelection && !useCustomUnderlines) 480 paintSelection(context, boxOrigin, selectionPaintStyle.fillColor);504 paintSelection(context, localPaintOffset, selectionPaintStyle.fillColor); 481 505 } 482 506 … … 580 604 581 605 if (paintInfo.phase == PaintPhaseForeground) { 582 paintDocumentMarkers(context, boxOrigin, false);606 paintDocumentMarkers(context, localPaintOffset, false); 583 607 584 608 if (useCustomUnderlines) … … 624 648 } 625 649 626 void InlineTextBox::paintSelection(GraphicsContext& context, const FloatPoint& boxOrigin, const Color& textColor)650 void InlineTextBox::paintSelection(GraphicsContext& context, const LayoutPoint& paintOffset, const Color& textColor) 627 651 { 628 652 #if ENABLE(TEXT_SELECTION) … … 651 675 // Note that if the text is truncated, we let the thing being painted in the truncation 652 676 // draw its own highlight. 653 auto text = this->text(); 654 TextRun textRun = createTextRun(text); 655 656 const RootInlineBox& rootBox = root(); 657 LayoutUnit selectionBottom = rootBox.selectionBottom(); 658 LayoutUnit selectionTop = rootBox.selectionTopAdjustedForPrecedingBlock(); 659 660 LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop; 661 LayoutUnit selectionHeight = std::max<LayoutUnit>(0, selectionBottom - selectionTop); 662 663 LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth, selectionHeight); 664 lineFont().adjustSelectionRectForText(textRun, selectionRect, selectionStart, selectionEnd); 677 auto selectionRect = localSelectionRectWithClampedPositions(selectionStart, selectionEnd); 678 selectionRect.moveBy(paintOffset); 665 679 666 680 // FIXME: Support painting combined text. 667 context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()), c);681 context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), isLeftToRightDirection()), c); 668 682 #else 669 683 UNUSED_PARAM(context); 670 UNUSED_PARAM( boxOrigin);684 UNUSED_PARAM(paintOffset); 671 685 UNUSED_PARAM(textColor); 672 686 #endif 673 687 } 674 688 675 inline void InlineTextBox::paintTextSubrangeBackground(GraphicsContext& context, const FloatPoint& boxOrigin, const Color& color, unsigned startOffset, unsigned endOffset)689 inline void InlineTextBox::paintTextSubrangeBackground(GraphicsContext& context, const LayoutPoint& paintOffset, const Color& color, unsigned startOffset, unsigned endOffset) 676 690 { 677 691 startOffset = clampedOffset(startOffset); … … 683 697 updateGraphicsContext(context, TextPaintStyle { color }); // Don't draw text at all! 684 698 685 // Use same y positioning and height as for selection, so that when the selection and this subrange are on 686 // the same word there are no pieces sticking out. 687 LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop(); 688 LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, 0, selectionHeight()); 689 690 auto text = this->text(); 691 TextRun textRun = createTextRun(text); 692 lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset); 699 auto selectionRect = localSelectionRectWithClampedPositions(startOffset, endOffset); 700 selectionRect.moveBy(paintOffset); 693 701 694 702 // FIXME: Support painting combined text. 695 context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()), color);696 } 697 698 void InlineTextBox::paintCompositionBackground(GraphicsContext& context, const FloatPoint& boxOrigin)699 { 700 paintTextSubrangeBackground(context, boxOrigin, renderer().frame().editor().compositionStart(), renderer().frame().editor().compositionEnd(), Color::compositionFill);701 } 702 703 void InlineTextBox::paintTextMatchMarker(GraphicsContext& context, const FloatPoint& boxOrigin, const MarkerSubrange& subrange, bool isActiveMatch)703 context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), isLeftToRightDirection()), color); 704 } 705 706 void InlineTextBox::paintCompositionBackground(GraphicsContext& context, const LayoutPoint& paintOffset) 707 { 708 paintTextSubrangeBackground(context, paintOffset, renderer().frame().editor().compositionStart(), renderer().frame().editor().compositionEnd(), Color::compositionFill); 709 } 710 711 void InlineTextBox::paintTextMatchMarker(GraphicsContext& context, const LayoutPoint& paintOffset, const MarkerSubrange& subrange, bool isActiveMatch) 704 712 { 705 713 if (!renderer().frame().editor().markedTextMatchesAreHighlighted()) 706 714 return; 707 715 auto highlightColor = isActiveMatch ? renderer().theme().platformActiveTextSearchHighlightColor() : renderer().theme().platformInactiveTextSearchHighlightColor(); 708 paintTextSubrangeBackground(context, boxOrigin, highlightColor, subrange.startOffset, subrange.endOffset);716 paintTextSubrangeBackground(context, paintOffset, highlightColor, subrange.startOffset, subrange.endOffset); 709 717 } 710 718 … … 759 767 } 760 768 761 void InlineTextBox::paintDocumentMarker(GraphicsContext& context, const FloatPoint& boxOrigin, const MarkerSubrange& subrange)769 void InlineTextBox::paintDocumentMarker(GraphicsContext& context, const LayoutPoint& paintOffset, const MarkerSubrange& subrange) 762 770 { 763 771 // Never print spelling/grammar markers (5327887) … … 767 775 if (m_truncation == cFullTruncation) 768 776 return; 769 770 float start = 0; // start of line to draw, relative to tx771 float width = m_logicalWidth; // how much line to draw772 777 773 778 // Determine whether we need to measure text … … 780 785 markerSpansWholeBox = false; 781 786 782 if (!markerSpansWholeBox) { 787 FloatPoint location; 788 float width; 789 if (markerSpansWholeBox) { 790 location = locationIncludingFlipping(); 791 width = m_logicalWidth; 792 } else { 783 793 unsigned startPosition = clampedOffset(subrange.startOffset); 784 794 unsigned endPosition = clampedOffset(subrange.endOffset); 785 795 786 // Calculate start & width 787 int deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop(); 788 int selHeight = selectionHeight(); 789 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); 790 auto text = this->text(); 791 TextRun run = createTextRun(text); 792 793 LayoutRect selectionRect = LayoutRect(startPoint, FloatSize(0, selHeight)); 794 lineFont().adjustSelectionRectForText(run, selectionRect, startPosition, endPosition); 795 IntRect markerRect = enclosingIntRect(selectionRect); 796 start = markerRect.x() - startPoint.x(); 797 width = markerRect.width(); 798 } 799 796 // We round to the nearest enclosing integral rect to avoid truncating the dot decoration on Cocoa platforms. 797 // FIXME: Find a better place to ensure that the Cocoa dots are not truncated. 798 auto selectionRect = localSelectionRectWithClampedPositions(startPosition, endPosition, SelectionRectRounding::EnclosingIntRect); 799 location = selectionRect.location(); 800 width = selectionRect.width(); 801 } 802 location.moveBy(paintOffset); 803 800 804 auto lineStyleForSubrangeType = [] (MarkerSubrange::Type type) { 801 805 switch (type) { … … 837 841 } 838 842 // FIXME: Support painting combined text. 839 context.drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + underlineOffset), width, lineStyleForSubrangeType(subrange.type)); 840 } 841 842 void InlineTextBox::paintDocumentMarkers(GraphicsContext& context, const FloatPoint& boxOrigin, bool background) 843 location.move(0, underlineOffset); 844 context.drawLineForDocumentMarker(location, width, lineStyleForSubrangeType(subrange.type)); 845 } 846 847 void InlineTextBox::paintDocumentMarkers(GraphicsContext& context, const LayoutPoint& paintOffset, bool background) 843 848 { 844 849 if (!renderer().textNode()) … … 934 939 for (auto& subrange : subdivide(subranges, OverlapStrategy::Frontmost)) { 935 940 if (subrange.type == MarkerSubrange::TextMatch) 936 paintTextMatchMarker(context, boxOrigin, subrange, subrange.marker->isActiveMatch());941 paintTextMatchMarker(context, paintOffset, subrange, subrange.marker->isActiveMatch()); 937 942 else 938 paintDocumentMarker(context, boxOrigin, subrange);943 paintDocumentMarker(context, paintOffset, subrange); 939 944 } 940 945 } -
trunk/Source/WebCore/rendering/InlineTextBox.h
r223552 r223699 111 111 FloatRect calculateBoundaries() const override { return FloatRect(x(), y(), width(), height()); } 112 112 113 virtual LayoutRect localSelectionRect(unsigned startPos , unsigned endPos) const;113 virtual LayoutRect localSelectionRect(unsigned startPosition, unsigned endPosition) const; 114 114 bool isSelected(unsigned startPosition, unsigned endPosition) const; 115 115 std::pair<unsigned, unsigned> selectionStartEnd() const; … … 153 153 void paintDecoration(GraphicsContext&, const TextRun&, const FloatPoint& textOrigin, const FloatRect& boxRect, 154 154 TextDecoration, TextPaintStyle, const ShadowData*, const FloatRect& clipOutRect); 155 void paintSelection(GraphicsContext&, const FloatPoint& boxOrigin, const Color&);155 void paintSelection(GraphicsContext&, const LayoutPoint& paintOffset, const Color&); 156 156 157 void paintDocumentMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkerSubrange&);158 void paintDocumentMarkers(GraphicsContext&, const FloatPoint& boxOrigin, bool background);159 void paintTextMatchMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkerSubrange&, bool isActiveMatch);157 void paintDocumentMarker(GraphicsContext&, const LayoutPoint& paintOffset, const MarkerSubrange&); 158 void paintDocumentMarkers(GraphicsContext&, const LayoutPoint& paintOffset, bool background); 159 void paintTextMatchMarker(GraphicsContext&, const LayoutPoint& paintOffset, const MarkerSubrange&, bool isActiveMatch); 160 160 161 void paintCompositionBackground(GraphicsContext&, const FloatPoint& boxOrigin);161 void paintCompositionBackground(GraphicsContext&, const LayoutPoint& paintOffset); 162 162 void paintCompositionUnderlines(GraphicsContext&, const FloatPoint& boxOrigin) const; 163 163 void paintCompositionUnderline(GraphicsContext&, const FloatPoint& boxOrigin, const CompositionUnderline&) const; 164 164 165 void paintTextSubrangeBackground(GraphicsContext&, const FloatPoint& boxOrigin, const Color&, unsigned startOffset, unsigned endOffset); 165 void paintTextSubrangeBackground(GraphicsContext&, const LayoutPoint& paintOffset, const Color&, unsigned startOffset, unsigned endOffset); 166 167 enum class SelectionRectRounding { None, EnclosingIntRect }; 168 LayoutRect localSelectionRectWithClampedPositions(unsigned clampedStartPosition, unsigned clampedEndPosition, SelectionRectRounding = SelectionRectRounding::None) const; 166 169 167 170 const RenderCombineText* combinedText() const;
Note: See TracChangeset
for help on using the changeset viewer.