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" |
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 "platform/graphics/paint/PaintRecord.h" |
| 22 #include "platform/graphics/paint/PaintRecorder.h" |
21 #include "platform/wtf/Optional.h" | 23 #include "platform/wtf/Optional.h" |
| 24 #include "third_party/skia/include/effects/SkGradientShader.h" |
22 | 25 |
23 namespace blink { | 26 namespace blink { |
24 | 27 |
25 namespace { | 28 namespace { |
26 | 29 |
27 std::pair<unsigned, unsigned> GetMarkerPaintOffsets( | 30 std::pair<unsigned, unsigned> GetMarkerPaintOffsets( |
28 const DocumentMarker& marker, | 31 const DocumentMarker& marker, |
29 const InlineTextBox& text_box) { | 32 const InlineTextBox& text_box) { |
30 const unsigned start_offset = marker.StartOffset() > text_box.Start() | 33 const unsigned start_offset = marker.StartOffset() > text_box.Start() |
31 ? marker.StartOffset() - text_box.Start() | 34 ? marker.StartOffset() - text_box.Start() |
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 UnderlinePaintEnd(underline)); | 1086 UnderlinePaintEnd(underline)); |
1084 else | 1087 else |
1085 PaintCompositionUnderline(paint_info.context, box_origin, underline); | 1088 PaintCompositionUnderline(paint_info.context, box_origin, underline); |
1086 } break; | 1089 } break; |
1087 default: | 1090 default: |
1088 ASSERT_NOT_REACHED(); | 1091 ASSERT_NOT_REACHED(); |
1089 } | 1092 } |
1090 } | 1093 } |
1091 } | 1094 } |
1092 | 1095 |
1093 static GraphicsContext::DocumentMarkerLineStyle LineStyleForMarkerType( | 1096 namespace { |
1094 DocumentMarker::MarkerType marker_type) { | 1097 |
1095 switch (marker_type) { | 1098 #if !OS(MACOSX) |
1096 case DocumentMarker::kSpelling: | 1099 |
1097 return GraphicsContext::kDocumentMarkerSpellingLineStyle; | 1100 sk_sp<PaintRecord> RecordMarker(DocumentMarker::MarkerType marker_type) { |
1098 case DocumentMarker::kGrammar: | 1101 SkColor color = (marker_type == DocumentMarker::kGrammar) |
1099 return GraphicsContext::kDocumentMarkerGrammarLineStyle; | 1102 ? SkColorSetRGB(0xC0, 0xC0, 0xC0) |
1100 default: | 1103 : SK_ColorRED; |
1101 ASSERT_NOT_REACHED(); | 1104 |
1102 return GraphicsContext::kDocumentMarkerSpellingLineStyle; | 1105 // Record the path equivalent to this legacy pattern: |
1103 } | 1106 // X o o X o o X |
| 1107 // o X o o X o |
| 1108 |
| 1109 static const float kW = 4; |
| 1110 static const float kH = 2; |
| 1111 |
| 1112 // Adjust the phase such that f' == 0 is "pixel"-centered |
| 1113 // (for optimal rasterization at native rez). |
| 1114 SkPath path; |
| 1115 path.moveTo(kW * -3 / 8, kH * 3 / 4); |
| 1116 path.cubicTo(kW * -1 / 8, kH * 3 / 4, |
| 1117 kW * -1 / 8, kH * 1 / 4, |
| 1118 kW * 1 / 8, kH * 1 / 4); |
| 1119 path.cubicTo(kW * 3 / 8, kH * 1 / 4, |
| 1120 kW * 3 / 8, kH * 3 / 4, |
| 1121 kW * 5 / 8, kH * 3 / 4); |
| 1122 path.cubicTo(kW * 7 / 8, kH * 3 / 4, |
| 1123 kW * 7 / 8, kH * 1 / 4, |
| 1124 kW * 9 / 8, kH * 1 / 4); |
| 1125 |
| 1126 PaintFlags flags; |
| 1127 flags.setAntiAlias(true); |
| 1128 flags.setColor(color); |
| 1129 flags.setStyle(PaintFlags::kStroke_Style); |
| 1130 flags.setStrokeWidth(kH * 1 / 2); |
| 1131 |
| 1132 PaintRecorder recorder; |
| 1133 recorder.beginRecording(kW, kH); |
| 1134 recorder.getRecordingCanvas()->drawPath(path, flags); |
| 1135 |
| 1136 return recorder.finishRecordingAsPicture(); |
1104 } | 1137 } |
1105 | 1138 |
| 1139 #else // OS(MACOSX) |
| 1140 |
| 1141 sk_sp<PaintRecord> RecordMarker(DocumentMarker::MarkerType marker_type) { |
| 1142 SkColor color = (marker_type == DocumentMarker::kGrammar) |
| 1143 ? SkColorSetRGB(0x6B, 0x6B, 0x6B) |
| 1144 : SkColorSetRGB(0xFB, 0x2D, 0x1D); |
| 1145 |
| 1146 // Match the artwork used by the Mac. |
| 1147 static const float kW = 4; |
| 1148 static const float kH = 3; |
| 1149 static const float kR = 1.5f; |
| 1150 |
| 1151 // top->bottom translucent gradient. |
| 1152 const SkColor colors[2] = { |
| 1153 SkColorSetARGB(0x48, |
| 1154 SkColorGetR(color), |
| 1155 SkColorGetG(color), |
| 1156 SkColorGetB(color)), |
| 1157 color |
| 1158 }; |
| 1159 const SkPoint pts[2] = { |
| 1160 SkPoint::Make(0, 0), |
| 1161 SkPoint::Make(0, 2 * kR) |
| 1162 }; |
| 1163 |
| 1164 PaintFlags flags; |
| 1165 flags.setAntiAlias(true); |
| 1166 flags.setColor(color); |
| 1167 flags.setShader(SkGradientShader::MakeLinear( |
| 1168 pts, colors, nullptr, ARRAY_SIZE(colors), SkShader::kClamp_TileMode)); |
| 1169 PaintRecorder recorder; |
| 1170 recorder.beginRecording(kW, kH); |
| 1171 recorder.getRecordingCanvas()->drawCircle(kR, kR, kR, flags); |
| 1172 |
| 1173 return recorder.finishRecordingAsPicture(); |
| 1174 } |
| 1175 |
| 1176 #endif // OS(MACOSX) |
| 1177 |
| 1178 void DrawDocumentMarker(GraphicsContext& context, |
| 1179 const FloatPoint& pt, |
| 1180 float width, |
| 1181 DocumentMarker::MarkerType marker_type, |
| 1182 float zoom) { |
| 1183 DCHECK(marker_type == DocumentMarker::kSpelling || |
| 1184 marker_type == DocumentMarker::kGrammar); |
| 1185 |
| 1186 DEFINE_STATIC_LOCAL(PaintRecord*, spelling_marker, |
| 1187 (RecordMarker(DocumentMarker::kSpelling).release())); |
| 1188 DEFINE_STATIC_LOCAL(PaintRecord*, grammar_marker, |
| 1189 (RecordMarker(DocumentMarker::kGrammar).release())); |
| 1190 const auto& marker = marker_type == DocumentMarker::kSpelling |
| 1191 ? spelling_marker |
| 1192 : grammar_marker; |
| 1193 |
| 1194 // Position already includes zoom and device scale factor. |
| 1195 SkScalar origin_x = WebCoreFloatToSkScalar(pt.X()); |
| 1196 SkScalar origin_y = WebCoreFloatToSkScalar(pt.Y()); |
| 1197 |
| 1198 #if OS(MACOSX) |
| 1199 // Make sure to draw only complete dots, and finish inside the marked text. |
| 1200 width -= fmodf(width, marker->cullRect().width() * zoom); |
| 1201 #else |
| 1202 // Offset it vertically by 1 so that there's some space under the text. |
| 1203 origin_y += 1; |
| 1204 #endif |
| 1205 |
| 1206 const auto rect = SkRect::MakeWH(width, marker->cullRect().height() * zoom); |
| 1207 const auto local_matrix = SkMatrix::MakeScale(zoom, zoom); |
| 1208 |
| 1209 PaintFlags flags; |
| 1210 flags.setAntiAlias(true); |
| 1211 flags.setShader(WrapSkShader(MakePaintShaderRecord( |
| 1212 sk_ref_sp(marker), SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode, |
| 1213 &local_matrix, nullptr))); |
| 1214 |
| 1215 // Apply the origin translation as a global transform. This ensures that the |
| 1216 // shader local matrix depends solely on zoom => Skia can reuse the same |
| 1217 // cached tile for all markers at a given zoom level. |
| 1218 GraphicsContextStateSaver saver(context); |
| 1219 context.Translate(origin_x, origin_y); |
| 1220 context.DrawRect(rect, flags); |
| 1221 } |
| 1222 |
| 1223 } // anonymous ns |
| 1224 |
1106 void InlineTextBoxPainter::PaintDocumentMarker(GraphicsContext& context, | 1225 void InlineTextBoxPainter::PaintDocumentMarker(GraphicsContext& context, |
1107 const LayoutPoint& box_origin, | 1226 const LayoutPoint& box_origin, |
1108 const DocumentMarker& marker, | 1227 const DocumentMarker& marker, |
1109 const ComputedStyle& style, | 1228 const ComputedStyle& style, |
1110 const Font& font, | 1229 const Font& font, |
1111 bool grammar) { | 1230 bool grammar) { |
1112 // Never print spelling/grammar markers (5327887) | 1231 // Never print spelling/grammar markers (5327887) |
1113 if (inline_text_box_.GetLineLayoutItem().GetDocument().Printing()) | 1232 if (inline_text_box_.GetLineLayoutItem().GetDocument().Printing()) |
1114 return; | 1233 return; |
1115 | 1234 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 int underline_offset; | 1298 int underline_offset; |
1180 if (descent <= (line_thickness + 2)) { | 1299 if (descent <= (line_thickness + 2)) { |
1181 // Place the underline at the very bottom of the text in small/medium fonts. | 1300 // Place the underline at the very bottom of the text in small/medium fonts. |
1182 underline_offset = | 1301 underline_offset = |
1183 (inline_text_box_.LogicalHeight() - line_thickness).ToInt(); | 1302 (inline_text_box_.LogicalHeight() - line_thickness).ToInt(); |
1184 } else { | 1303 } else { |
1185 // In larger fonts, though, place the underline up near the baseline to | 1304 // In larger fonts, though, place the underline up near the baseline to |
1186 // prevent a big gap. | 1305 // prevent a big gap. |
1187 underline_offset = baseline + 2; | 1306 underline_offset = baseline + 2; |
1188 } | 1307 } |
1189 context.DrawLineForDocumentMarker( | 1308 DrawDocumentMarker(context, |
1190 FloatPoint((box_origin.X() + start).ToFloat(), | 1309 FloatPoint((box_origin.X() + start).ToFloat(), |
1191 (box_origin.Y() + underline_offset).ToFloat()), | 1310 (box_origin.Y() + underline_offset).ToFloat()), |
1192 width.ToFloat(), LineStyleForMarkerType(marker.GetType()), | 1311 width.ToFloat(), marker.GetType(), style.EffectiveZoom()); |
1193 style.EffectiveZoom()); | |
1194 } | 1312 } |
1195 | 1313 |
1196 template <InlineTextBoxPainter::PaintOptions options> | 1314 template <InlineTextBoxPainter::PaintOptions options> |
1197 void InlineTextBoxPainter::PaintSelection(GraphicsContext& context, | 1315 void InlineTextBoxPainter::PaintSelection(GraphicsContext& context, |
1198 const LayoutRect& box_rect, | 1316 const LayoutRect& box_rect, |
1199 const ComputedStyle& style, | 1317 const ComputedStyle& style, |
1200 const Font& font, | 1318 const Font& font, |
1201 Color text_color, | 1319 Color text_color, |
1202 LayoutTextCombine* combined_text) { | 1320 LayoutTextCombine* combined_text) { |
1203 // See if we have a selection to paint at all. | 1321 // See if we have a selection to paint at all. |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 | 1571 |
1454 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), | 1572 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), |
1455 inline_text_box_.LogicalHeight())); | 1573 inline_text_box_.LogicalHeight())); |
1456 context.Clip(FloatRect(box_rect)); | 1574 context.Clip(FloatRect(box_rect)); |
1457 context.DrawHighlightForText(font, run, FloatPoint(box_origin), | 1575 context.DrawHighlightForText(font, run, FloatPoint(box_origin), |
1458 box_rect.Height().ToInt(), color, | 1576 box_rect.Height().ToInt(), color, |
1459 paint_offsets.first, paint_offsets.second); | 1577 paint_offsets.first, paint_offsets.second); |
1460 } | 1578 } |
1461 | 1579 |
1462 } // namespace blink | 1580 } // namespace blink |
OLD | NEW |