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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 const InlineTextBox* inline_text_box) { | 74 const InlineTextBox* inline_text_box) { |
75 bool first_line = inline_text_box->IsFirstLineStyle(); | 75 bool first_line = inline_text_box->IsFirstLineStyle(); |
76 for (LineLayoutItem current = inline_text_box->Parent()->GetLineLayoutItem(); | 76 for (LineLayoutItem current = inline_text_box->Parent()->GetLineLayoutItem(); |
77 ;) { | 77 ;) { |
78 if (current.IsLayoutBlock()) | 78 if (current.IsLayoutBlock()) |
79 return current; | 79 return current; |
80 if (!current.IsLayoutInline() || current.IsRubyText()) | 80 if (!current.IsLayoutInline() || current.IsRubyText()) |
81 return nullptr; | 81 return nullptr; |
82 | 82 |
83 const ComputedStyle& style_to_use = current.StyleRef(first_line); | 83 const ComputedStyle& style_to_use = current.StyleRef(first_line); |
84 if (style_to_use.GetTextDecoration() & kTextDecorationUnderline) | 84 if (EnumHasFlags(style_to_use.GetTextDecoration(), |
| 85 TextDecoration::kUnderline)) |
85 return current; | 86 return current; |
86 | 87 |
87 current = current.Parent(); | 88 current = current.Parent(); |
88 if (!current) | 89 if (!current) |
89 return current; | 90 return current; |
90 | 91 |
91 if (Node* node = current.GetNode()) { | 92 if (Node* node = current.GetNode()) { |
92 if (isHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag)) | 93 if (isHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag)) |
93 return current; | 94 return current; |
94 } | 95 } |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 ResolveUnderlinePosition(*decoration_info.style, &box); | 585 ResolveUnderlinePosition(*decoration_info.style, &box); |
585 bool flip_underline_and_overline = false; | 586 bool flip_underline_and_overline = false; |
586 if (underline_position == ResolvedUnderlinePosition::kOver) { | 587 if (underline_position == ResolvedUnderlinePosition::kOver) { |
587 flip_underline_and_overline = true; | 588 flip_underline_and_overline = true; |
588 underline_position = ResolvedUnderlinePosition::kUnder; | 589 underline_position = ResolvedUnderlinePosition::kUnder; |
589 } | 590 } |
590 | 591 |
591 for (const AppliedTextDecoration& decoration : decorations) { | 592 for (const AppliedTextDecoration& decoration : decorations) { |
592 TextDecoration lines = decoration.Lines(); | 593 TextDecoration lines = decoration.Lines(); |
593 if (flip_underline_and_overline) { | 594 if (flip_underline_and_overline) { |
594 lines = static_cast<TextDecoration>( | 595 lines ^= (TextDecoration::kUnderline | TextDecoration::kOverline); |
595 lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); | |
596 } | 596 } |
597 if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { | 597 if (EnumHasFlags(lines, TextDecoration::kUnderline) && |
| 598 decoration_info.font_data) { |
598 const int underline_offset = | 599 const int underline_offset = |
599 ComputeUnderlineOffset(underline_position, *decoration_info.style, | 600 ComputeUnderlineOffset(underline_position, *decoration_info.style, |
600 decoration_info.font_data->GetFontMetrics(), | 601 decoration_info.font_data->GetFontMetrics(), |
601 &box, decoration_info.thickness); | 602 &box, decoration_info.thickness); |
602 AppliedDecorationPainter decoration_painter( | 603 AppliedDecorationPainter decoration_painter( |
603 context, decoration_info, underline_offset, decoration, | 604 context, decoration_info, underline_offset, decoration, |
604 decoration_info.double_offset, 1); | 605 decoration_info.double_offset, 1); |
605 if (skip_intercepts) { | 606 if (skip_intercepts) { |
606 text_painter.ClipDecorationsStripe( | 607 text_painter.ClipDecorationsStripe( |
607 -decoration_info.baseline + | 608 -decoration_info.baseline + |
608 decoration_painter.DecorationBounds().Y() - | 609 decoration_painter.DecorationBounds().Y() - |
609 decoration_info.local_origin.Y(), | 610 decoration_info.local_origin.Y(), |
610 decoration_painter.DecorationBounds().Height(), | 611 decoration_painter.DecorationBounds().Height(), |
611 decoration_info.thickness); | 612 decoration_info.thickness); |
612 } | 613 } |
613 decoration_painter.Paint(); | 614 decoration_painter.Paint(); |
614 } | 615 } |
615 if (lines & kTextDecorationOverline) { | 616 if (EnumHasFlags(lines, TextDecoration::kOverline)) { |
616 const int overline_offset = | 617 const int overline_offset = |
617 ComputeOverlineOffset(*decoration_info.style, &box); | 618 ComputeOverlineOffset(*decoration_info.style, &box); |
618 AppliedDecorationPainter decoration_painter( | 619 AppliedDecorationPainter decoration_painter( |
619 context, decoration_info, overline_offset, decoration, | 620 context, decoration_info, overline_offset, decoration, |
620 -decoration_info.double_offset, 1); | 621 -decoration_info.double_offset, 1); |
621 if (skip_intercepts) { | 622 if (skip_intercepts) { |
622 text_painter.ClipDecorationsStripe( | 623 text_painter.ClipDecorationsStripe( |
623 -decoration_info.baseline + | 624 -decoration_info.baseline + |
624 decoration_painter.DecorationBounds().Y() - | 625 decoration_painter.DecorationBounds().Y() - |
625 decoration_info.local_origin.Y(), | 626 decoration_info.local_origin.Y(), |
626 decoration_painter.DecorationBounds().Height(), | 627 decoration_painter.DecorationBounds().Height(), |
627 decoration_info.thickness); | 628 decoration_info.thickness); |
628 } | 629 } |
629 decoration_painter.Paint(); | 630 decoration_painter.Paint(); |
630 } | 631 } |
631 // We could instead build a vector of the TextDecoration instances needing | 632 // We could instead build a vector of the TextDecoration instances needing |
632 // line-through but this is a rare case so better to avoid vector overhead. | 633 // line-through but this is a rare case so better to avoid vector overhead. |
633 has_line_through_decoration |= ((lines & kTextDecorationLineThrough) != 0); | 634 has_line_through_decoration |= |
| 635 EnumHasFlags(lines, TextDecoration::kLineThrough); |
634 } | 636 } |
635 } | 637 } |
636 | 638 |
637 static void PaintDecorationsOnlyLineThrough( | 639 static void PaintDecorationsOnlyLineThrough( |
638 TextPainter& text_painter, | 640 TextPainter& text_painter, |
639 const DecorationInfo& decoration_info, | 641 const DecorationInfo& decoration_info, |
640 const PaintInfo& paint_info, | 642 const PaintInfo& paint_info, |
641 const Vector<AppliedTextDecoration>& decorations) { | 643 const Vector<AppliedTextDecoration>& decorations) { |
642 GraphicsContext& context = paint_info.context; | 644 GraphicsContext& context = paint_info.context; |
643 GraphicsContextStateSaver state_saver(context); | 645 GraphicsContextStateSaver state_saver(context); |
644 context.SetStrokeThickness(decoration_info.thickness); | 646 context.SetStrokeThickness(decoration_info.thickness); |
645 for (const AppliedTextDecoration& decoration : decorations) { | 647 for (const AppliedTextDecoration& decoration : decorations) { |
646 TextDecoration lines = decoration.Lines(); | 648 TextDecoration lines = decoration.Lines(); |
647 if (lines & kTextDecorationLineThrough) { | 649 if (EnumHasFlags(lines, TextDecoration::kLineThrough)) { |
648 const float line_through_offset = 2 * decoration_info.baseline / 3; | 650 const float line_through_offset = 2 * decoration_info.baseline / 3; |
649 AppliedDecorationPainter decoration_painter( | 651 AppliedDecorationPainter decoration_painter( |
650 context, decoration_info, line_through_offset, decoration, | 652 context, decoration_info, line_through_offset, decoration, |
651 decoration_info.double_offset, 0); | 653 decoration_info.double_offset, 0); |
652 // No skip: ink for line-through, | 654 // No skip: ink for line-through, |
653 // compare https://github.com/w3c/csswg-drafts/issues/711 | 655 // compare https://github.com/w3c/csswg-drafts/issues/711 |
654 decoration_painter.Paint(); | 656 decoration_painter.Paint(); |
655 } | 657 } |
656 } | 658 } |
657 } | 659 } |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 emphasis_mark_position); | 855 emphasis_mark_position); |
854 if (combined_text) | 856 if (combined_text) |
855 text_painter.SetCombinedText(combined_text); | 857 text_painter.SetCombinedText(combined_text); |
856 if (inline_text_box_.Truncation() != kCNoTruncation && ltr != flow_is_ltr) | 858 if (inline_text_box_.Truncation() != kCNoTruncation && ltr != flow_is_ltr) |
857 text_painter.SetEllipsisOffset(inline_text_box_.Truncation()); | 859 text_painter.SetEllipsisOffset(inline_text_box_.Truncation()); |
858 | 860 |
859 if (!paint_selected_text_only) { | 861 if (!paint_selected_text_only) { |
860 // Paint text decorations except line-through. | 862 // Paint text decorations except line-through. |
861 DecorationInfo decoration_info; | 863 DecorationInfo decoration_info; |
862 bool has_line_through_decoration = false; | 864 bool has_line_through_decoration = false; |
863 if (style_to_use.TextDecorationsInEffect() != kTextDecorationNone && | 865 if (style_to_use.TextDecorationsInEffect() != TextDecoration::kNone && |
864 inline_text_box_.Truncation() != kCFullTruncation) { | 866 inline_text_box_.Truncation() != kCFullTruncation) { |
865 ComputeDecorationInfo(decoration_info, inline_text_box_, box_origin, | 867 ComputeDecorationInfo(decoration_info, inline_text_box_, box_origin, |
866 style_to_use.AppliedTextDecorations()); | 868 style_to_use.AppliedTextDecorations()); |
867 GraphicsContextStateSaver state_saver(context, false); | 869 GraphicsContextStateSaver state_saver(context, false); |
868 PrepareContextForDecoration(context, state_saver, | 870 PrepareContextForDecoration(context, state_saver, |
869 inline_text_box_.IsHorizontal(), text_style, | 871 inline_text_box_.IsHorizontal(), text_style, |
870 combined_text, box_rect); | 872 combined_text, box_rect); |
871 PaintDecorationsExceptLineThrough( | 873 PaintDecorationsExceptLineThrough( |
872 text_painter, has_line_through_decoration, inline_text_box_, | 874 text_painter, has_line_through_decoration, inline_text_box_, |
873 decoration_info, paint_info, style_to_use.AppliedTextDecorations()); | 875 decoration_info, paint_info, style_to_use.AppliedTextDecorations()); |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 | 1455 |
1454 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), | 1456 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), |
1455 inline_text_box_.LogicalHeight())); | 1457 inline_text_box_.LogicalHeight())); |
1456 context.Clip(FloatRect(box_rect)); | 1458 context.Clip(FloatRect(box_rect)); |
1457 context.DrawHighlightForText(font, run, FloatPoint(box_origin), | 1459 context.DrawHighlightForText(font, run, FloatPoint(box_origin), |
1458 box_rect.Height().ToInt(), color, | 1460 box_rect.Height().ToInt(), color, |
1459 paint_offsets.first, paint_offsets.second); | 1461 paint_offsets.first, paint_offsets.second); |
1460 } | 1462 } |
1461 | 1463 |
1462 } // namespace blink | 1464 } // namespace blink |
OLD | NEW |