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" | |
8 #include "core/editing/Editor.h" | 7 #include "core/editing/Editor.h" |
9 #include "core/editing/markers/CompositionMarker.h" | 8 #include "core/editing/markers/CompositionMarker.h" |
10 #include "core/editing/markers/DocumentMarkerController.h" | 9 #include "core/editing/markers/DocumentMarkerController.h" |
11 #include "core/editing/markers/TextMatchMarker.h" | 10 #include "core/editing/markers/TextMatchMarker.h" |
12 #include "core/frame/LocalFrame.h" | 11 #include "core/frame/LocalFrame.h" |
13 #include "core/layout/LayoutTextCombine.h" | 12 #include "core/layout/LayoutTextCombine.h" |
14 #include "core/layout/LayoutTheme.h" | 13 #include "core/layout/LayoutTheme.h" |
15 #include "core/layout/api/LineLayoutAPIShim.h" | 14 #include "core/layout/api/LineLayoutAPIShim.h" |
16 #include "core/layout/api/LineLayoutBox.h" | 15 #include "core/layout/api/LineLayoutBox.h" |
17 #include "core/layout/line/InlineTextBox.h" | 16 #include "core/layout/line/InlineTextBox.h" |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 // expect PaintPhaseSelection. The existing haveSelection logic in paint() | 531 // expect PaintPhaseSelection. The existing haveSelection logic in paint() |
533 // tests for != PaintPhaseTextClip. | 532 // tests for != PaintPhaseTextClip. |
534 if (inline_text_box_.GetLineLayoutItem().Style()->Visibility() != | 533 if (inline_text_box_.GetLineLayoutItem().Style()->Visibility() != |
535 EVisibility::kVisible || | 534 EVisibility::kVisible || |
536 inline_text_box_.Truncation() == kCFullTruncation || | 535 inline_text_box_.Truncation() == kCFullTruncation || |
537 !inline_text_box_.Len()) | 536 !inline_text_box_.Len()) |
538 return false; | 537 return false; |
539 return true; | 538 return true; |
540 } | 539 } |
541 | 540 |
542 unsigned InlineTextBoxPainter::UnderlinePaintStart( | 541 unsigned InlineTextBoxPainter::MarkerPaintStart(const DocumentMarker& marker) { |
543 const CompositionUnderline& underline) { | |
544 DCHECK(inline_text_box_.Truncation() != kCFullTruncation); | 542 DCHECK(inline_text_box_.Truncation() != kCFullTruncation); |
545 DCHECK(inline_text_box_.Len()); | 543 DCHECK(inline_text_box_.Len()); |
546 | 544 |
547 // Start painting at the beginning of the text or the specified underline | 545 // Start painting at the beginning of the text or the specified underline |
548 // start offset, whichever is higher. | 546 // start offset, whichever is higher. |
549 unsigned paint_start = | 547 unsigned paint_start = |
550 std::max(inline_text_box_.Start(), underline.StartOffset()); | 548 std::max(inline_text_box_.Start(), marker.StartOffset()); |
551 // Cap the maximum paint start to (if no truncation) the last character, | 549 // Cap the maximum paint start to (if no truncation) the last character, |
552 // else the last character before the truncation ellipsis. | 550 // else the last character before the truncation ellipsis. |
553 return std::min(paint_start, (inline_text_box_.Truncation() == kCNoTruncation) | 551 return std::min(paint_start, (inline_text_box_.Truncation() == kCNoTruncation) |
554 ? inline_text_box_.end() | 552 ? inline_text_box_.end() |
555 : inline_text_box_.Start() + | 553 : inline_text_box_.Start() + |
556 inline_text_box_.Truncation() - 1); | 554 inline_text_box_.Truncation() - 1); |
557 } | 555 } |
558 | 556 |
559 unsigned InlineTextBoxPainter::UnderlinePaintEnd( | 557 unsigned InlineTextBoxPainter::MarkerPaintEnd(const DocumentMarker& marker) { |
560 const CompositionUnderline& underline) { | |
561 DCHECK(inline_text_box_.Truncation() != kCFullTruncation); | 558 DCHECK(inline_text_box_.Truncation() != kCFullTruncation); |
562 DCHECK(inline_text_box_.Len()); | 559 DCHECK(inline_text_box_.Len()); |
563 | 560 |
564 // End painting just past the end of the text or the specified underline end | 561 // End painting just past the end of the text or the specified underline end |
565 // offset, whichever is lower. | 562 // offset, whichever is lower. |
566 unsigned paint_end = std::min( | 563 unsigned paint_end = std::min( |
567 inline_text_box_.end() + 1, | 564 inline_text_box_.end() + 1, |
568 underline.EndOffset()); // end() points at the last char, not past it. | 565 marker.EndOffset()); // end() points at the last char, not past it. |
569 // Cap the maximum paint end to (if no truncation) one past the last | 566 // Cap the maximum paint end to (if no truncation) one past the last |
570 // character, else one past the last character before the truncation | 567 // character, else one past the last character before the truncation |
571 // ellipsis. | 568 // ellipsis. |
572 return std::min(paint_end, (inline_text_box_.Truncation() == kCNoTruncation) | 569 return std::min(paint_end, (inline_text_box_.Truncation() == kCNoTruncation) |
573 ? inline_text_box_.end() + 1 | 570 ? inline_text_box_.end() + 1 |
574 : inline_text_box_.Start() + | 571 : inline_text_box_.Start() + |
575 inline_text_box_.Truncation()); | 572 inline_text_box_.Truncation()); |
576 } | 573 } |
577 | 574 |
578 void InlineTextBoxPainter::PaintSingleCompositionBackgroundRun( | 575 void InlineTextBoxPainter::PaintSingleMarkerBackgroundRun( |
579 GraphicsContext& context, | 576 GraphicsContext& context, |
580 const LayoutPoint& box_origin, | 577 const LayoutPoint& box_origin, |
581 const ComputedStyle& style, | 578 const ComputedStyle& style, |
582 const Font& font, | 579 const Font& font, |
583 Color background_color, | 580 Color background_color, |
584 int start_pos, | 581 int start_pos, |
585 int end_pos) { | 582 int end_pos) { |
586 if (background_color == Color::kTransparent) | 583 if (background_color == Color::kTransparent) |
587 return; | 584 return; |
588 | 585 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 inline_text_box_.PaintTextMatchMarkerBackground( | 669 inline_text_box_.PaintTextMatchMarkerBackground( |
673 paint_info, box_origin, ToTextMatchMarker(marker), style, font); | 670 paint_info, box_origin, ToTextMatchMarker(marker), style, font); |
674 } else { | 671 } else { |
675 inline_text_box_.PaintTextMatchMarkerForeground( | 672 inline_text_box_.PaintTextMatchMarkerForeground( |
676 paint_info, box_origin, ToTextMatchMarker(marker), style, font); | 673 paint_info, box_origin, ToTextMatchMarker(marker), style, font); |
677 } | 674 } |
678 break; | 675 break; |
679 case DocumentMarker::kComposition: | 676 case DocumentMarker::kComposition: |
680 case DocumentMarker::kActiveSuggestion: { | 677 case DocumentMarker::kActiveSuggestion: { |
681 const StyleableMarker& styleable_marker = ToStyleableMarker(marker); | 678 const StyleableMarker& styleable_marker = ToStyleableMarker(marker); |
682 CompositionUnderline underline( | 679 if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) { |
683 styleable_marker.StartOffset(), styleable_marker.EndOffset(), | 680 PaintSingleMarkerBackgroundRun(paint_info.context, box_origin, style, |
684 styleable_marker.UnderlineColor(), styleable_marker.IsThick(), | 681 font, |
685 styleable_marker.BackgroundColor()); | 682 styleable_marker.BackgroundColor(), |
686 if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) | 683 MarkerPaintStart(styleable_marker), |
687 PaintSingleCompositionBackgroundRun( | 684 MarkerPaintEnd(styleable_marker)); |
688 paint_info.context, box_origin, style, font, | 685 } else { |
689 underline.BackgroundColor(), UnderlinePaintStart(underline), | 686 PaintStyleableMarkerUnderline(paint_info.context, box_origin, |
690 UnderlinePaintEnd(underline)); | 687 styleable_marker); |
691 else | 688 } |
692 PaintCompositionUnderline(paint_info.context, box_origin, underline); | |
693 } break; | 689 } break; |
694 default: | 690 default: |
695 NOTREACHED(); | 691 NOTREACHED(); |
696 } | 692 } |
697 } | 693 } |
698 } | 694 } |
699 | 695 |
700 namespace { | 696 namespace { |
701 | 697 |
702 #if !OS(MACOSX) | 698 #if !OS(MACOSX) |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 LayoutRect& rect) { | 1023 LayoutRect& rect) { |
1028 FloatRectOutsets outsets = FloatRectOutsets(); | 1024 FloatRectOutsets outsets = FloatRectOutsets(); |
1029 float space_width = inline_text_box_.NewlineSpaceWidth(); | 1025 float space_width = inline_text_box_.NewlineSpaceWidth(); |
1030 if (inline_text_box_.IsLeftToRightDirection()) | 1026 if (inline_text_box_.IsLeftToRightDirection()) |
1031 outsets.SetRight(space_width); | 1027 outsets.SetRight(space_width); |
1032 else | 1028 else |
1033 outsets.SetLeft(space_width); | 1029 outsets.SetLeft(space_width); |
1034 rect.Expand(outsets); | 1030 rect.Expand(outsets); |
1035 } | 1031 } |
1036 | 1032 |
1037 void InlineTextBoxPainter::PaintCompositionUnderline( | 1033 void InlineTextBoxPainter::PaintStyleableMarkerUnderline( |
1038 GraphicsContext& context, | 1034 GraphicsContext& context, |
1039 const LayoutPoint& box_origin, | 1035 const LayoutPoint& box_origin, |
1040 const CompositionUnderline& underline) { | 1036 const StyleableMarker& marker) { |
1041 if (underline.GetColor() == Color::kTransparent) | 1037 if (marker.UnderlineColor() == Color::kTransparent) |
1042 return; | 1038 return; |
1043 | 1039 |
1044 if (inline_text_box_.Truncation() == kCFullTruncation) | 1040 if (inline_text_box_.Truncation() == kCFullTruncation) |
1045 return; | 1041 return; |
1046 | 1042 |
1047 unsigned paint_start = UnderlinePaintStart(underline); | 1043 unsigned paint_start = MarkerPaintStart(marker); |
1048 unsigned paint_end = UnderlinePaintEnd(underline); | 1044 unsigned paint_end = MarkerPaintEnd(marker); |
1049 DCHECK_LT(paint_start, paint_end); | 1045 DCHECK_LT(paint_start, paint_end); |
1050 | 1046 |
1051 // start of line to draw | 1047 // start of line to draw |
1052 float start = | 1048 float start = |
1053 paint_start == inline_text_box_.Start() | 1049 paint_start == inline_text_box_.Start() |
1054 ? 0 | 1050 ? 0 |
1055 : inline_text_box_.GetLineLayoutItem().Width( | 1051 : inline_text_box_.GetLineLayoutItem().Width( |
1056 inline_text_box_.Start(), | 1052 inline_text_box_.Start(), |
1057 paint_start - inline_text_box_.Start(), | 1053 paint_start - inline_text_box_.Start(), |
1058 inline_text_box_.TextPos(), | 1054 inline_text_box_.TextPos(), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 // thick. If there's not enough space the underline will touch or overlap | 1087 // thick. If there's not enough space the underline will touch or overlap |
1092 // characters. | 1088 // characters. |
1093 int line_thickness = 1; | 1089 int line_thickness = 1; |
1094 const SimpleFontData* font_data = | 1090 const SimpleFontData* font_data = |
1095 inline_text_box_.GetLineLayoutItem() | 1091 inline_text_box_.GetLineLayoutItem() |
1096 .Style(inline_text_box_.IsFirstLineStyle()) | 1092 .Style(inline_text_box_.IsFirstLineStyle()) |
1097 ->GetFont() | 1093 ->GetFont() |
1098 .PrimaryFont(); | 1094 .PrimaryFont(); |
1099 DCHECK(font_data); | 1095 DCHECK(font_data); |
1100 int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0; | 1096 int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0; |
1101 if (underline.Thick() && inline_text_box_.LogicalHeight() - baseline >= 2) | 1097 if (marker.IsThick() && inline_text_box_.LogicalHeight() - baseline >= 2) |
1102 line_thickness = 2; | 1098 line_thickness = 2; |
1103 | 1099 |
1104 // We need to have some space between underlines of subsequent clauses, | 1100 // We need to have some space between underlines of subsequent clauses, |
1105 // because some input methods do not use different underline styles for those. | 1101 // because some input methods do not use different underline styles for those. |
1106 // We make each line shorter, which has a harmless side effect of shortening | 1102 // We make each line shorter, which has a harmless side effect of shortening |
1107 // the first and last clauses, too. | 1103 // the first and last clauses, too. |
1108 start += 1; | 1104 start += 1; |
1109 width -= 2; | 1105 width -= 2; |
1110 | 1106 |
1111 context.SetStrokeColor(underline.GetColor()); | 1107 context.SetStrokeColor(marker.UnderlineColor()); |
1112 context.SetStrokeThickness(line_thickness); | 1108 context.SetStrokeThickness(line_thickness); |
1113 context.DrawLineForText( | 1109 context.DrawLineForText( |
1114 FloatPoint( | 1110 FloatPoint( |
1115 box_origin.X() + start, | 1111 box_origin.X() + start, |
1116 (box_origin.Y() + inline_text_box_.LogicalHeight() - line_thickness) | 1112 (box_origin.Y() + inline_text_box_.LogicalHeight() - line_thickness) |
1117 .ToFloat()), | 1113 .ToFloat()), |
1118 width); | 1114 width); |
1119 } | 1115 } |
1120 | 1116 |
1121 void InlineTextBoxPainter::PaintTextMatchMarkerForeground( | 1117 void InlineTextBoxPainter::PaintTextMatchMarkerForeground( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 | 1178 |
1183 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), | 1179 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), |
1184 inline_text_box_.LogicalHeight())); | 1180 inline_text_box_.LogicalHeight())); |
1185 context.Clip(FloatRect(box_rect)); | 1181 context.Clip(FloatRect(box_rect)); |
1186 context.DrawHighlightForText(font, run, FloatPoint(box_origin), | 1182 context.DrawHighlightForText(font, run, FloatPoint(box_origin), |
1187 box_rect.Height().ToInt(), color, | 1183 box_rect.Height().ToInt(), color, |
1188 paint_offsets.first, paint_offsets.second); | 1184 paint_offsets.first, paint_offsets.second); |
1189 } | 1185 } |
1190 | 1186 |
1191 } // namespace blink | 1187 } // namespace blink |
OLD | NEW |