Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp

Issue 2599483002: Extract helper function. (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/InlineTextBoxPainter.h" 5 #include "core/paint/InlineTextBoxPainter.h"
6 6
7 #include "core/editing/CompositionUnderline.h" 7 #include "core/editing/CompositionUnderline.h"
8 #include "core/editing/Editor.h" 8 #include "core/editing/Editor.h"
9 #include "core/editing/markers/DocumentMarkerController.h" 9 #include "core/editing/markers/DocumentMarkerController.h"
10 #include "core/frame/LocalFrame.h" 10 #include "core/frame/LocalFrame.h"
11 #include "core/layout/LayoutTextCombine.h" 11 #include "core/layout/LayoutTextCombine.h"
12 #include "core/layout/LayoutTheme.h" 12 #include "core/layout/LayoutTheme.h"
13 #include "core/layout/api/LineLayoutAPIShim.h" 13 #include "core/layout/api/LineLayoutAPIShim.h"
14 #include "core/layout/api/LineLayoutBox.h" 14 #include "core/layout/api/LineLayoutBox.h"
15 #include "core/layout/line/InlineTextBox.h" 15 #include "core/layout/line/InlineTextBox.h"
16 #include "core/paint/PaintInfo.h" 16 #include "core/paint/PaintInfo.h"
17 #include "core/paint/TextPainter.h" 17 #include "core/paint/TextPainter.h"
18 #include "core/style/AppliedTextDecoration.h" 18 #include "core/style/AppliedTextDecoration.h"
19 #include "platform/graphics/GraphicsContextStateSaver.h" 19 #include "platform/graphics/GraphicsContextStateSaver.h"
20 #include "platform/graphics/paint/DrawingRecorder.h" 20 #include "platform/graphics/paint/DrawingRecorder.h"
21 #include "wtf/Optional.h" 21 #include "wtf/Optional.h"
22 22
23 namespace blink { 23 namespace blink {
24 24
25 namespace {
26
27 std::pair<unsigned, unsigned> GetMarkerPaintOffsets(
28 const DocumentMarker& marker,
29 const InlineTextBox& textBox) {
30 const unsigned startOffset = marker.startOffset() > textBox.start()
chrishtr 2016/12/23 20:57:19 Why not just use std::max like the code used to?
Andrey Kraynov 2016/12/23 22:27:47 But then it will look like |std::max(someUnsignedI
Andrey Kraynov 2016/12/23 22:31:00 Greater then or equal to 0, of course.
31 ? marker.startOffset() - textBox.start()
32 : 0U;
33 const unsigned endOffset =
34 std::min(marker.endOffset() - textBox.start(), textBox.len());
35 return std::make_pair(startOffset, endOffset);
36 }
37 }
38
25 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, 39 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
26 const FontMetrics& fontMetrics, 40 const FontMetrics& fontMetrics,
27 const InlineTextBox* inlineTextBox, 41 const InlineTextBox* inlineTextBox,
28 const float textDecorationThickness) { 42 const float textDecorationThickness) {
29 // Compute the gap between the font and the underline. Use at least one 43 // Compute the gap between the font and the underline. Use at least one
30 // pixel gap, if underline is thick then use a bigger gap. 44 // pixel gap, if underline is thick then use a bigger gap.
31 int gap = 0; 45 int gap = 0;
32 46
33 // Underline position of zero means draw underline on Baseline Position, 47 // Underline position of zero means draw underline on Baseline Position,
34 // in Blink we need at least 1-pixel gap to adding following check. 48 // in Blink we need at least 1-pixel gap to adding following check.
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 743
730 DocumentMarkerVector markers = 744 DocumentMarkerVector markers =
731 m_inlineTextBox.getLineLayoutItem().document().markers().markersFor( 745 m_inlineTextBox.getLineLayoutItem().document().markers().markersFor(
732 m_inlineTextBox.getLineLayoutItem().node()); 746 m_inlineTextBox.getLineLayoutItem().node());
733 DocumentMarkerVector::const_iterator markerIt = markers.begin(); 747 DocumentMarkerVector::const_iterator markerIt = markers.begin();
734 748
735 // Give any document markers that touch this run a chance to draw before the 749 // Give any document markers that touch this run a chance to draw before the
736 // text has been drawn. Note end() points at the last char, not one past it 750 // text has been drawn. Note end() points at the last char, not one past it
737 // like endOffset and ranges do. 751 // like endOffset and ranges do.
738 for (; markerIt != markers.end(); ++markerIt) { 752 for (; markerIt != markers.end(); ++markerIt) {
739 DocumentMarker* marker = *markerIt; 753 DCHECK(*markerIt);
754 const DocumentMarker& marker = **markerIt;
740 755
741 // Paint either the background markers or the foreground markers, but not 756 // Paint either the background markers or the foreground markers, but not
742 // both. 757 // both.
743 switch (marker->type()) { 758 switch (marker.type()) {
744 case DocumentMarker::Grammar: 759 case DocumentMarker::Grammar:
745 case DocumentMarker::Spelling: 760 case DocumentMarker::Spelling:
746 if (markerPaintPhase == DocumentMarkerPaintPhase::Background) 761 if (markerPaintPhase == DocumentMarkerPaintPhase::Background)
747 continue; 762 continue;
748 break; 763 break;
749 case DocumentMarker::TextMatch: 764 case DocumentMarker::TextMatch:
750 case DocumentMarker::Composition: 765 case DocumentMarker::Composition:
751 break; 766 break;
752 default: 767 default:
753 continue; 768 continue;
754 } 769 }
755 770
756 if (marker->endOffset() <= m_inlineTextBox.start()) { 771 if (marker.endOffset() <= m_inlineTextBox.start()) {
757 // marker is completely before this run. This might be a marker that sits 772 // marker is completely before this run. This might be a marker that sits
758 // before the first run we draw, or markers that were within runs we 773 // before the first run we draw, or markers that were within runs we
759 // skipped due to truncation. 774 // skipped due to truncation.
760 continue; 775 continue;
761 } 776 }
762 if (marker->startOffset() > m_inlineTextBox.end()) { 777 if (marker.startOffset() > m_inlineTextBox.end()) {
763 // marker is completely after this run, bail. A later run will paint it. 778 // marker is completely after this run, bail. A later run will paint it.
764 break; 779 break;
765 } 780 }
766 781
767 // marker intersects this run. Paint it. 782 // marker intersects this run. Paint it.
768 switch (marker->type()) { 783 switch (marker.type()) {
769 case DocumentMarker::Spelling: 784 case DocumentMarker::Spelling:
770 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin, 785 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin,
771 marker, style, font, false); 786 marker, style, font, false);
772 break; 787 break;
773 case DocumentMarker::Grammar: 788 case DocumentMarker::Grammar:
774 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin, 789 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin,
775 marker, style, font, true); 790 marker, style, font, true);
776 break; 791 break;
777 case DocumentMarker::TextMatch: 792 case DocumentMarker::TextMatch:
778 if (markerPaintPhase == DocumentMarkerPaintPhase::Background) 793 if (markerPaintPhase == DocumentMarkerPaintPhase::Background)
779 m_inlineTextBox.paintTextMatchMarkerBackground(paintInfo, boxOrigin, 794 m_inlineTextBox.paintTextMatchMarkerBackground(paintInfo, boxOrigin,
780 marker, style, font); 795 marker, style, font);
781 else 796 else
782 m_inlineTextBox.paintTextMatchMarkerForeground(paintInfo, boxOrigin, 797 m_inlineTextBox.paintTextMatchMarkerForeground(paintInfo, boxOrigin,
783 marker, style, font); 798 marker, style, font);
784 break; 799 break;
785 case DocumentMarker::Composition: { 800 case DocumentMarker::Composition: {
786 CompositionUnderline underline( 801 CompositionUnderline underline(marker.startOffset(), marker.endOffset(),
787 marker->startOffset(), marker->endOffset(), 802 marker.underlineColor(), marker.thick(),
788 marker->underlineColor(), marker->thick(), 803 marker.backgroundColor());
789 marker->backgroundColor());
790 if (markerPaintPhase == DocumentMarkerPaintPhase::Background) 804 if (markerPaintPhase == DocumentMarkerPaintPhase::Background)
791 paintSingleCompositionBackgroundRun( 805 paintSingleCompositionBackgroundRun(
792 paintInfo.context, boxOrigin, style, font, 806 paintInfo.context, boxOrigin, style, font,
793 underline.backgroundColor(), underlinePaintStart(underline), 807 underline.backgroundColor(), underlinePaintStart(underline),
794 underlinePaintEnd(underline)); 808 underlinePaintEnd(underline));
795 else 809 else
796 paintCompositionUnderline(paintInfo.context, boxOrigin, underline); 810 paintCompositionUnderline(paintInfo.context, boxOrigin, underline);
797 } break; 811 } break;
798 default: 812 default:
799 ASSERT_NOT_REACHED(); 813 ASSERT_NOT_REACHED();
800 } 814 }
801 } 815 }
802 } 816 }
803 817
804 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType( 818 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(
805 DocumentMarker::MarkerType markerType) { 819 DocumentMarker::MarkerType markerType) {
806 switch (markerType) { 820 switch (markerType) {
807 case DocumentMarker::Spelling: 821 case DocumentMarker::Spelling:
808 return GraphicsContext::DocumentMarkerSpellingLineStyle; 822 return GraphicsContext::DocumentMarkerSpellingLineStyle;
809 case DocumentMarker::Grammar: 823 case DocumentMarker::Grammar:
810 return GraphicsContext::DocumentMarkerGrammarLineStyle; 824 return GraphicsContext::DocumentMarkerGrammarLineStyle;
811 default: 825 default:
812 ASSERT_NOT_REACHED(); 826 ASSERT_NOT_REACHED();
813 return GraphicsContext::DocumentMarkerSpellingLineStyle; 827 return GraphicsContext::DocumentMarkerSpellingLineStyle;
814 } 828 }
815 } 829 }
816 830
817 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext& context, 831 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext& context,
818 const LayoutPoint& boxOrigin, 832 const LayoutPoint& boxOrigin,
819 DocumentMarker* marker, 833 const DocumentMarker& marker,
820 const ComputedStyle& style, 834 const ComputedStyle& style,
821 const Font& font, 835 const Font& font,
822 bool grammar) { 836 bool grammar) {
823 // Never print spelling/grammar markers (5327887) 837 // Never print spelling/grammar markers (5327887)
824 if (m_inlineTextBox.getLineLayoutItem().document().printing()) 838 if (m_inlineTextBox.getLineLayoutItem().document().printing())
825 return; 839 return;
826 840
827 if (m_inlineTextBox.truncation() == cFullTruncation) 841 if (m_inlineTextBox.truncation() == cFullTruncation)
828 return; 842 return;
829 843
830 LayoutUnit start; // start of line to draw, relative to tx 844 LayoutUnit start; // start of line to draw, relative to tx
831 LayoutUnit width = m_inlineTextBox.logicalWidth(); // how much line to draw 845 LayoutUnit width = m_inlineTextBox.logicalWidth(); // how much line to draw
832 846
833 // Determine whether we need to measure text 847 // Determine whether we need to measure text
834 bool markerSpansWholeBox = true; 848 bool markerSpansWholeBox = true;
835 if (m_inlineTextBox.start() <= marker->startOffset()) 849 if (m_inlineTextBox.start() <= marker.startOffset())
836 markerSpansWholeBox = false; 850 markerSpansWholeBox = false;
837 if ((m_inlineTextBox.end() + 1) != 851 if ((m_inlineTextBox.end() + 1) !=
838 marker->endOffset()) // end points at the last char, not past it 852 marker.endOffset()) // end points at the last char, not past it
839 markerSpansWholeBox = false; 853 markerSpansWholeBox = false;
840 if (m_inlineTextBox.truncation() != cNoTruncation) 854 if (m_inlineTextBox.truncation() != cNoTruncation)
841 markerSpansWholeBox = false; 855 markerSpansWholeBox = false;
842 856
843 if (!markerSpansWholeBox || grammar) { 857 if (!markerSpansWholeBox || grammar) {
844 int startPosition = 858 int startPosition, endPosition;
845 std::max<int>(marker->startOffset() - m_inlineTextBox.start(), 0); 859 std::tie(startPosition, endPosition) =
846 int endPosition = std::min<int>( 860 GetMarkerPaintOffsets(marker, m_inlineTextBox);
847 marker->endOffset() - static_cast<int>(m_inlineTextBox.start()),
848 m_inlineTextBox.len());
849 861
850 if (m_inlineTextBox.truncation() != cNoTruncation) 862 if (m_inlineTextBox.truncation() != cNoTruncation)
851 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation()); 863 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation());
852 864
853 // Calculate start & width 865 // Calculate start & width
854 int deltaY = (m_inlineTextBox.getLineLayoutItem() 866 int deltaY = (m_inlineTextBox.getLineLayoutItem()
855 .style() 867 .style()
856 ->isFlippedLinesWritingMode() 868 ->isFlippedLinesWritingMode()
857 ? m_inlineTextBox.root().selectionBottom() - 869 ? m_inlineTextBox.root().selectionBottom() -
858 m_inlineTextBox.logicalBottom() 870 m_inlineTextBox.logicalBottom()
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 // Place the underline at the very bottom of the text in small/medium fonts. 905 // Place the underline at the very bottom of the text in small/medium fonts.
894 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt(); 906 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt();
895 } else { 907 } else {
896 // In larger fonts, though, place the underline up near the baseline to 908 // In larger fonts, though, place the underline up near the baseline to
897 // prevent a big gap. 909 // prevent a big gap.
898 underlineOffset = baseline + 2; 910 underlineOffset = baseline + 2;
899 } 911 }
900 context.drawLineForDocumentMarker( 912 context.drawLineForDocumentMarker(
901 FloatPoint((boxOrigin.x() + start).toFloat(), 913 FloatPoint((boxOrigin.x() + start).toFloat(),
902 (boxOrigin.y() + underlineOffset).toFloat()), 914 (boxOrigin.y() + underlineOffset).toFloat()),
903 width.toFloat(), lineStyleForMarkerType(marker->type())); 915 width.toFloat(), lineStyleForMarkerType(marker.type()));
904 } 916 }
905 917
906 template <InlineTextBoxPainter::PaintOptions options> 918 template <InlineTextBoxPainter::PaintOptions options>
907 void InlineTextBoxPainter::paintSelection(GraphicsContext& context, 919 void InlineTextBoxPainter::paintSelection(GraphicsContext& context,
908 const LayoutRect& boxRect, 920 const LayoutRect& boxRect,
909 const ComputedStyle& style, 921 const ComputedStyle& style,
910 const Font& font, 922 const Font& font,
911 Color textColor, 923 Color textColor,
912 LayoutTextCombine* combinedText) { 924 LayoutTextCombine* combinedText) {
913 // See if we have a selection to paint at all. 925 // See if we have a selection to paint at all.
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 FloatPoint( 1211 FloatPoint(
1200 boxOrigin.x() + start, 1212 boxOrigin.x() + start,
1201 (boxOrigin.y() + m_inlineTextBox.logicalHeight() - lineThickness) 1213 (boxOrigin.y() + m_inlineTextBox.logicalHeight() - lineThickness)
1202 .toFloat()), 1214 .toFloat()),
1203 width); 1215 width);
1204 } 1216 }
1205 1217
1206 void InlineTextBoxPainter::paintTextMatchMarkerForeground( 1218 void InlineTextBoxPainter::paintTextMatchMarkerForeground(
1207 const PaintInfo& paintInfo, 1219 const PaintInfo& paintInfo,
1208 const LayoutPoint& boxOrigin, 1220 const LayoutPoint& boxOrigin,
1209 DocumentMarker* marker, 1221 const DocumentMarker& marker,
1210 const ComputedStyle& style, 1222 const ComputedStyle& style,
1211 const Font& font) { 1223 const Font& font) {
1212 if (!inlineLayoutObject().frame()->editor().markedTextMatchesAreHighlighted()) 1224 if (!inlineLayoutObject().frame()->editor().markedTextMatchesAreHighlighted())
1213 return; 1225 return;
1214 1226
1215 // TODO(ramya.v): Extract this into a helper function and share many copies of 1227 const auto paintOffsets = GetMarkerPaintOffsets(marker, m_inlineTextBox);
1216 // this code.
1217 int sPos =
1218 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0);
Andrey Kraynov 2016/12/21 17:43:18 This is obviously pointless call to std::max() fun
1219 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(),
1220 m_inlineTextBox.len());
1221 TextRun run = m_inlineTextBox.constructTextRun(style); 1228 TextRun run = m_inlineTextBox.constructTextRun(style);
1222 1229
1223 Color textColor = 1230 Color textColor =
1224 LayoutTheme::theme().platformTextSearchColor(marker->activeMatch()); 1231 LayoutTheme::theme().platformTextSearchColor(marker.activeMatch());
1225 if (style.visitedDependentColor(CSSPropertyColor) == textColor) 1232 if (style.visitedDependentColor(CSSPropertyColor) == textColor)
1226 return; 1233 return;
1227 1234
1228 const SimpleFontData* fontData = font.primaryFont(); 1235 const SimpleFontData* fontData = font.primaryFont();
1229 DCHECK(fontData); 1236 DCHECK(fontData);
1230 if (!fontData) 1237 if (!fontData)
1231 return; 1238 return;
1232 1239
1233 TextPainter::Style textStyle; 1240 TextPainter::Style textStyle;
1234 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = 1241 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor =
1235 textStyle.emphasisMarkColor = textColor; 1242 textStyle.emphasisMarkColor = textColor;
1236 textStyle.strokeWidth = style.textStrokeWidth(); 1243 textStyle.strokeWidth = style.textStrokeWidth();
1237 textStyle.shadow = 0; 1244 textStyle.shadow = 0;
1238 1245
1239 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), 1246 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(),
1240 m_inlineTextBox.logicalHeight())); 1247 m_inlineTextBox.logicalHeight()));
1241 LayoutPoint textOrigin(boxOrigin.x(), 1248 LayoutPoint textOrigin(boxOrigin.x(),
1242 boxOrigin.y() + fontData->getFontMetrics().ascent()); 1249 boxOrigin.y() + fontData->getFontMetrics().ascent());
1243 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, 1250 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect,
1244 m_inlineTextBox.isHorizontal()); 1251 m_inlineTextBox.isHorizontal());
1245 1252
1246 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); 1253 textPainter.paint(paintOffsets.first, paintOffsets.second,
1254 m_inlineTextBox.len(), textStyle, 0);
1247 } 1255 }
1248 1256
1249 void InlineTextBoxPainter::paintTextMatchMarkerBackground( 1257 void InlineTextBoxPainter::paintTextMatchMarkerBackground(
1250 const PaintInfo& paintInfo, 1258 const PaintInfo& paintInfo,
1251 const LayoutPoint& boxOrigin, 1259 const LayoutPoint& boxOrigin,
1252 DocumentMarker* marker, 1260 const DocumentMarker& marker,
1253 const ComputedStyle& style, 1261 const ComputedStyle& style,
1254 const Font& font) { 1262 const Font& font) {
1255 if (!LineLayoutAPIShim::layoutObjectFrom(m_inlineTextBox.getLineLayoutItem()) 1263 if (!LineLayoutAPIShim::layoutObjectFrom(m_inlineTextBox.getLineLayoutItem())
1256 ->frame() 1264 ->frame()
1257 ->editor() 1265 ->editor()
1258 .markedTextMatchesAreHighlighted()) 1266 .markedTextMatchesAreHighlighted())
1259 return; 1267 return;
1260 1268
1261 int sPos = 1269 const auto paintOffsets = GetMarkerPaintOffsets(marker, m_inlineTextBox);
1262 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0);
1263 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(),
1264 m_inlineTextBox.len());
1265 TextRun run = m_inlineTextBox.constructTextRun(style); 1270 TextRun run = m_inlineTextBox.constructTextRun(style);
1266 1271
1267 Color color = LayoutTheme::theme().platformTextSearchHighlightColor( 1272 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(
1268 marker->activeMatch()); 1273 marker.activeMatch());
1269 GraphicsContext& context = paintInfo.context; 1274 GraphicsContext& context = paintInfo.context;
1270 GraphicsContextStateSaver stateSaver(context); 1275 GraphicsContextStateSaver stateSaver(context);
1271 1276
1272 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), 1277 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(),
1273 m_inlineTextBox.logicalHeight())); 1278 m_inlineTextBox.logicalHeight()));
1274 context.clip(FloatRect(boxRect)); 1279 context.clip(FloatRect(boxRect));
1275 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), 1280 context.drawHighlightForText(font, run, FloatPoint(boxOrigin),
1276 boxRect.height().toInt(), color, sPos, ePos); 1281 boxRect.height().toInt(), color,
1282 paintOffsets.first, paintOffsets.second);
1277 } 1283 }
1278 1284
1279 } // namespace blink 1285 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698