| OLD | NEW |
| 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" |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 TextPainter::Style textStyle = TextPainter::textPaintingStyle( | 178 TextPainter::Style textStyle = TextPainter::textPaintingStyle( |
| 179 m_inlineTextBox.getLineLayoutItem(), styleToUse, paintInfo); | 179 m_inlineTextBox.getLineLayoutItem(), styleToUse, paintInfo); |
| 180 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle( | 180 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle( |
| 181 m_inlineTextBox.getLineLayoutItem(), haveSelection, paintInfo, textStyle); | 181 m_inlineTextBox.getLineLayoutItem(), haveSelection, paintInfo, textStyle); |
| 182 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 182 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); |
| 183 bool paintSelectedTextSeparately = | 183 bool paintSelectedTextSeparately = |
| 184 !paintSelectedTextOnly && textStyle != selectionStyle; | 184 !paintSelectedTextOnly && textStyle != selectionStyle; |
| 185 | 185 |
| 186 // Set our font. | 186 // Set our font. |
| 187 const Font& font = styleToUse.font(); | 187 const Font& font = styleToUse.font(); |
| 188 const SimpleFontData* fontData = font.primaryFont(); |
| 189 DCHECK(fontData); |
| 188 | 190 |
| 189 LayoutPoint textOrigin(boxOrigin.x(), | 191 int ascent = fontData ? fontData->getFontMetrics().ascent() : 0; |
| 190 boxOrigin.y() + font.getFontMetrics().ascent()); | 192 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + ascent); |
| 191 | 193 |
| 192 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds | 194 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds |
| 193 // include selection and composition highlights. | 195 // include selection and composition highlights. |
| 194 if (paintInfo.phase != PaintPhaseSelection && | 196 if (paintInfo.phase != PaintPhaseSelection && |
| 195 paintInfo.phase != PaintPhaseTextClip && !isPrinting) { | 197 paintInfo.phase != PaintPhaseTextClip && !isPrinting) { |
| 196 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, | 198 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, |
| 197 DocumentMarkerPaintPhase::Background); | 199 DocumentMarkerPaintPhase::Background); |
| 198 | 200 |
| 199 const LayoutObject& textBoxLayoutObject = inlineLayoutObject(); | 201 const LayoutObject& textBoxLayoutObject = inlineLayoutObject(); |
| 200 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { | 202 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 547 |
| 546 // IMPORTANT: The misspelling underline is not considered when calculating the | 548 // IMPORTANT: The misspelling underline is not considered when calculating the |
| 547 // text bounds, so we have to make sure to fit within those bounds. This | 549 // text bounds, so we have to make sure to fit within those bounds. This |
| 548 // means the top pixel(s) of the underline will overlap the bottom pixel(s) of | 550 // means the top pixel(s) of the underline will overlap the bottom pixel(s) of |
| 549 // the glyphs in smaller font sizes. The alternatives are to increase the | 551 // the glyphs in smaller font sizes. The alternatives are to increase the |
| 550 // line spacing (bad!!) or decrease the underline thickness. The overlap is | 552 // line spacing (bad!!) or decrease the underline thickness. The overlap is |
| 551 // actually the most useful, and matches what AppKit does. So, we generally | 553 // actually the most useful, and matches what AppKit does. So, we generally |
| 552 // place the underline at the bottom of the text, but in larger fonts that's | 554 // place the underline at the bottom of the text, but in larger fonts that's |
| 553 // not so good so we pin to two pixels under the baseline. | 555 // not so good so we pin to two pixels under the baseline. |
| 554 int lineThickness = misspellingLineThickness; | 556 int lineThickness = misspellingLineThickness; |
| 555 int baseline = m_inlineTextBox.getLineLayoutItem() | 557 |
| 556 .style(m_inlineTextBox.isFirstLineStyle()) | 558 const SimpleFontData* fontData = |
| 557 ->getFontMetrics() | 559 m_inlineTextBox.getLineLayoutItem() |
| 558 .ascent(); | 560 .style(m_inlineTextBox.isFirstLineStyle()) |
| 561 ->font() |
| 562 .primaryFont(); |
| 563 DCHECK(fontData); |
| 564 int baseline = fontData ? fontData->getFontMetrics().ascent() : 0; |
| 559 int descent = (m_inlineTextBox.logicalHeight() - baseline).toInt(); | 565 int descent = (m_inlineTextBox.logicalHeight() - baseline).toInt(); |
| 560 int underlineOffset; | 566 int underlineOffset; |
| 561 if (descent <= (lineThickness + 2)) { | 567 if (descent <= (lineThickness + 2)) { |
| 562 // Place the underline at the very bottom of the text in small/medium fonts. | 568 // Place the underline at the very bottom of the text in small/medium fonts. |
| 563 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt(); | 569 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt(); |
| 564 } else { | 570 } else { |
| 565 // In larger fonts, though, place the underline up near the baseline to | 571 // In larger fonts, though, place the underline up near the baseline to |
| 566 // prevent a big gap. | 572 // prevent a big gap. |
| 567 underlineOffset = baseline + 2; | 573 underlineOffset = baseline + 2; |
| 568 } | 574 } |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 true); | 952 true); |
| 947 if (m_inlineTextBox.isFirstLineStyle()) | 953 if (m_inlineTextBox.isFirstLineStyle()) |
| 948 textBoxLayoutObject.getTextDecorations(deco, underline, overline, | 954 textBoxLayoutObject.getTextDecorations(deco, underline, overline, |
| 949 linethrough, true, true); | 955 linethrough, true, true); |
| 950 | 956 |
| 951 // Use a special function for underlines to get the positioning exactly right. | 957 // Use a special function for underlines to get the positioning exactly right. |
| 952 bool isPrinting = paintInfo.isPrinting(); | 958 bool isPrinting = paintInfo.isPrinting(); |
| 953 | 959 |
| 954 const ComputedStyle& styleToUse = | 960 const ComputedStyle& styleToUse = |
| 955 textBoxLayoutObject.styleRef(m_inlineTextBox.isFirstLineStyle()); | 961 textBoxLayoutObject.styleRef(m_inlineTextBox.isFirstLineStyle()); |
| 956 float baseline = styleToUse.getFontMetrics().ascent(); | 962 const SimpleFontData* fontData = styleToUse.font().primaryFont(); |
| 963 DCHECK(fontData); |
| 964 float baseline = fontData ? fontData->getFontMetrics().ascent() : 0; |
| 957 | 965 |
| 958 // Set the thick of the line to be 10% (or something else ?)of the computed | 966 // Set the thick of the line to be 10% (or something else ?)of the computed |
| 959 // font size and not less than 1px. Using computedFontSize should take care | 967 // font size and not less than 1px. Using computedFontSize should take care |
| 960 // of zoom as well. | 968 // of zoom as well. |
| 961 | 969 |
| 962 // Update Underline thickness, in case we have Faulty Font Metrics calculating | 970 // Update Underline thickness, in case we have Faulty Font Metrics calculating |
| 963 // underline thickness by old method. | 971 // underline thickness by old method. |
| 964 float textDecorationThickness = | 972 float textDecorationThickness = 0.0; |
| 965 styleToUse.getFontMetrics().underlineThickness(); | 973 int fontHeightInt = 0; |
| 966 int fontHeightInt = (int)(styleToUse.getFontMetrics().floatHeight() + 0.5); | 974 if (fontData) { |
| 975 textDecorationThickness = fontData->getFontMetrics().underlineThickness(); |
| 976 fontHeightInt = (int)(fontData->getFontMetrics().floatHeight() + 0.5); |
| 977 } |
| 967 if ((textDecorationThickness == 0.f) || | 978 if ((textDecorationThickness == 0.f) || |
| 968 (textDecorationThickness >= (fontHeightInt >> 1))) | 979 (textDecorationThickness >= (fontHeightInt >> 1))) |
| 969 textDecorationThickness = | 980 textDecorationThickness = |
| 970 std::max(1.f, styleToUse.computedFontSize() / 10.f); | 981 std::max(1.f, styleToUse.computedFontSize() / 10.f); |
| 971 | 982 |
| 972 context.setStrokeThickness(textDecorationThickness); | 983 context.setStrokeThickness(textDecorationThickness); |
| 973 | 984 |
| 974 bool antialiasDecoration = shouldSetDecorationAntialias( | 985 bool antialiasDecoration = shouldSetDecorationAntialias( |
| 975 overline.style, underline.style, linethrough.style); | 986 overline.style, underline.style, linethrough.style); |
| 976 | 987 |
| 977 // Offset between lines - always non-zero, so lines never cross each other. | 988 // Offset between lines - always non-zero, so lines never cross each other. |
| 978 float doubleOffset = textDecorationThickness + 1.f; | 989 float doubleOffset = textDecorationThickness + 1.f; |
| 979 | 990 |
| 980 if (deco & TextDecorationUnderline) { | 991 if ((deco & TextDecorationUnderline) && fontData) { |
| 981 const int underlineOffset = computeUnderlineOffset( | 992 const int underlineOffset = computeUnderlineOffset( |
| 982 styleToUse.getTextUnderlinePosition(), styleToUse.getFontMetrics(), | 993 styleToUse.getTextUnderlinePosition(), fontData->getFontMetrics(), |
| 983 &m_inlineTextBox, textDecorationThickness); | 994 &m_inlineTextBox, textDecorationThickness); |
| 984 paintAppliedDecoration( | 995 paintAppliedDecoration( |
| 985 context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), | 996 context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), |
| 986 width.toFloat(), doubleOffset, 1, underline, textDecorationThickness, | 997 width.toFloat(), doubleOffset, 1, underline, textDecorationThickness, |
| 987 antialiasDecoration, isPrinting); | 998 antialiasDecoration, isPrinting); |
| 988 } | 999 } |
| 989 if (deco & TextDecorationOverline) { | 1000 if (deco & TextDecorationOverline) { |
| 990 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat(), | 1001 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat(), |
| 991 -doubleOffset, 1, overline, textDecorationThickness, | 1002 -doubleOffset, 1, overline, textDecorationThickness, |
| 992 antialiasDecoration, isPrinting); | 1003 antialiasDecoration, isPrinting); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 // |logicalWidth| - |start| - |width|. We will draw that line, but backwards: | 1057 // |logicalWidth| - |start| - |width|. We will draw that line, but backwards: |
| 1047 // |logicalWidth| - |start| - |width| to |logicalWidth| - |start|. | 1058 // |logicalWidth| - |start| - |width| to |logicalWidth| - |start|. |
| 1048 if (!flowIsLTR) | 1059 if (!flowIsLTR) |
| 1049 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; | 1060 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; |
| 1050 | 1061 |
| 1051 // Thick marked text underlines are 2px thick as long as there is room for the | 1062 // Thick marked text underlines are 2px thick as long as there is room for the |
| 1052 // 2px line under the baseline. All other marked text underlines are 1px | 1063 // 2px line under the baseline. All other marked text underlines are 1px |
| 1053 // thick. If there's not enough space the underline will touch or overlap | 1064 // thick. If there's not enough space the underline will touch or overlap |
| 1054 // characters. | 1065 // characters. |
| 1055 int lineThickness = 1; | 1066 int lineThickness = 1; |
| 1056 int baseline = m_inlineTextBox.getLineLayoutItem() | 1067 const SimpleFontData* fontData = |
| 1057 .style(m_inlineTextBox.isFirstLineStyle()) | 1068 m_inlineTextBox.getLineLayoutItem() |
| 1058 ->getFontMetrics() | 1069 .style(m_inlineTextBox.isFirstLineStyle()) |
| 1059 .ascent(); | 1070 ->font() |
| 1071 .primaryFont(); |
| 1072 DCHECK(fontData); |
| 1073 int baseline = fontData ? fontData->getFontMetrics().ascent() : 0; |
| 1060 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2) | 1074 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2) |
| 1061 lineThickness = 2; | 1075 lineThickness = 2; |
| 1062 | 1076 |
| 1063 // We need to have some space between underlines of subsequent clauses, | 1077 // We need to have some space between underlines of subsequent clauses, |
| 1064 // because some input methods do not use different underline styles for those. | 1078 // because some input methods do not use different underline styles for those. |
| 1065 // We make each line shorter, which has a harmless side effect of shortening | 1079 // We make each line shorter, which has a harmless side effect of shortening |
| 1066 // the first and last clauses, too. | 1080 // the first and last clauses, too. |
| 1067 start += 1; | 1081 start += 1; |
| 1068 width -= 2; | 1082 width -= 2; |
| 1069 | 1083 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1091 int sPos = | 1105 int sPos = |
| 1092 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0); | 1106 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0); |
| 1093 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), | 1107 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), |
| 1094 m_inlineTextBox.len()); | 1108 m_inlineTextBox.len()); |
| 1095 TextRun run = m_inlineTextBox.constructTextRun(style); | 1109 TextRun run = m_inlineTextBox.constructTextRun(style); |
| 1096 | 1110 |
| 1097 Color textColor = | 1111 Color textColor = |
| 1098 LayoutTheme::theme().platformTextSearchColor(marker->activeMatch()); | 1112 LayoutTheme::theme().platformTextSearchColor(marker->activeMatch()); |
| 1099 if (style.visitedDependentColor(CSSPropertyColor) == textColor) | 1113 if (style.visitedDependentColor(CSSPropertyColor) == textColor) |
| 1100 return; | 1114 return; |
| 1115 |
| 1116 const SimpleFontData* fontData = font.primaryFont(); |
| 1117 DCHECK(fontData); |
| 1118 if (!fontData) |
| 1119 return; |
| 1120 |
| 1101 TextPainter::Style textStyle; | 1121 TextPainter::Style textStyle; |
| 1102 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = | 1122 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = |
| 1103 textStyle.emphasisMarkColor = textColor; | 1123 textStyle.emphasisMarkColor = textColor; |
| 1104 textStyle.strokeWidth = style.textStrokeWidth(); | 1124 textStyle.strokeWidth = style.textStrokeWidth(); |
| 1105 textStyle.shadow = 0; | 1125 textStyle.shadow = 0; |
| 1106 | 1126 |
| 1107 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), | 1127 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), |
| 1108 m_inlineTextBox.logicalHeight())); | 1128 m_inlineTextBox.logicalHeight())); |
| 1109 LayoutPoint textOrigin(boxOrigin.x(), | 1129 LayoutPoint textOrigin(boxOrigin.x(), |
| 1110 boxOrigin.y() + font.getFontMetrics().ascent()); | 1130 boxOrigin.y() + fontData->getFontMetrics().ascent()); |
| 1111 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, | 1131 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, |
| 1112 m_inlineTextBox.isHorizontal()); | 1132 m_inlineTextBox.isHorizontal()); |
| 1113 | 1133 |
| 1114 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); | 1134 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); |
| 1115 } | 1135 } |
| 1116 | 1136 |
| 1117 void InlineTextBoxPainter::paintTextMatchMarkerBackground( | 1137 void InlineTextBoxPainter::paintTextMatchMarkerBackground( |
| 1118 const PaintInfo& paintInfo, | 1138 const PaintInfo& paintInfo, |
| 1119 const LayoutPoint& boxOrigin, | 1139 const LayoutPoint& boxOrigin, |
| 1120 DocumentMarker* marker, | 1140 DocumentMarker* marker, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1138 GraphicsContextStateSaver stateSaver(context); | 1158 GraphicsContextStateSaver stateSaver(context); |
| 1139 | 1159 |
| 1140 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), | 1160 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), |
| 1141 m_inlineTextBox.logicalHeight())); | 1161 m_inlineTextBox.logicalHeight())); |
| 1142 context.clip(FloatRect(boxRect)); | 1162 context.clip(FloatRect(boxRect)); |
| 1143 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), | 1163 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), |
| 1144 boxRect.height().toInt(), color, sPos, ePos); | 1164 boxRect.height().toInt(), color, sPos, ePos); |
| 1145 } | 1165 } |
| 1146 | 1166 |
| 1147 } // namespace blink | 1167 } // namespace blink |
| OLD | NEW |