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 25 matching lines...) Expand all Loading... | |
36 const unsigned end_offset = | 36 const unsigned end_offset = |
37 std::min(marker.EndOffset() - text_box.Start(), text_box.Len()); | 37 std::min(marker.EndOffset() - text_box.Start(), text_box.Len()); |
38 return std::make_pair(start_offset, end_offset); | 38 return std::make_pair(start_offset, end_offset); |
39 } | 39 } |
40 } | 40 } |
41 | 41 |
42 enum class ResolvedUnderlinePosition { kRoman, kUnder, kOver }; | 42 enum class ResolvedUnderlinePosition { kRoman, kUnder, kOver }; |
43 | 43 |
44 static ResolvedUnderlinePosition ResolveUnderlinePosition( | 44 static ResolvedUnderlinePosition ResolveUnderlinePosition( |
45 const ComputedStyle& style, | 45 const ComputedStyle& style, |
46 const InlineTextBox* inline_text_box) { | 46 FontBaseline baseline_type) { |
47 // |auto| should resolve to |under| to avoid drawing through glyphs in | 47 // |auto| should resolve to |under| to avoid drawing through glyphs in |
48 // scripts where it would not be appropriate (e.g., ideographs.) | 48 // scripts where it would not be appropriate (e.g., ideographs.) |
49 // However, this has performance implications. For now, we only work with | 49 // However, this has performance implications. For now, we only work with |
50 // vertical text. | 50 // vertical text. |
51 switch (inline_text_box->Root().BaselineType()) { | 51 switch (baseline_type) { |
52 default: | |
53 NOTREACHED(); | |
54 // Fall though. | |
55 case kAlphabeticBaseline: | 52 case kAlphabeticBaseline: |
56 switch (style.GetTextUnderlinePosition()) { | 53 switch (style.GetTextUnderlinePosition()) { |
57 default: | |
58 NOTREACHED(); | |
59 // Fall though. | |
60 case kTextUnderlinePositionAuto: | 54 case kTextUnderlinePositionAuto: |
61 return ResolvedUnderlinePosition::kRoman; | 55 return ResolvedUnderlinePosition::kRoman; |
62 case kTextUnderlinePositionUnder: | 56 case kTextUnderlinePositionUnder: |
63 return ResolvedUnderlinePosition::kUnder; | 57 return ResolvedUnderlinePosition::kUnder; |
64 } | 58 } |
65 break; | 59 break; |
66 case kIdeographicBaseline: | 60 case kIdeographicBaseline: |
67 // Compute language-appropriate default underline position. | 61 // Compute language-appropriate default underline position. |
68 // https://drafts.csswg.org/css-text-decor-3/#default-stylesheet | 62 // https://drafts.csswg.org/css-text-decor-3/#default-stylesheet |
69 UScriptCode script = style.GetFontDescription().GetScript(); | 63 UScriptCode script = style.GetFontDescription().GetScript(); |
70 if (script == USCRIPT_KATAKANA_OR_HIRAGANA || script == USCRIPT_HANGUL) | 64 if (script == USCRIPT_KATAKANA_OR_HIRAGANA || script == USCRIPT_HANGUL) |
71 return ResolvedUnderlinePosition::kOver; | 65 return ResolvedUnderlinePosition::kOver; |
72 return ResolvedUnderlinePosition::kUnder; | 66 return ResolvedUnderlinePosition::kUnder; |
73 } | 67 } |
68 NOTREACHED(); | |
69 return ResolvedUnderlinePosition::kRoman; | |
74 } | 70 } |
75 | 71 |
76 static LineLayoutItem EnclosingUnderlineObject( | 72 static LineLayoutItem EnclosingUnderlineObject( |
77 const InlineTextBox* inline_text_box) { | 73 const InlineTextBox* inline_text_box) { |
78 bool first_line = inline_text_box->IsFirstLineStyle(); | 74 bool first_line = inline_text_box->IsFirstLineStyle(); |
79 for (LineLayoutItem current = inline_text_box->Parent()->GetLineLayoutItem(); | 75 for (LineLayoutItem current = inline_text_box->Parent()->GetLineLayoutItem(); |
80 ;) { | 76 ;) { |
81 if (current.IsLayoutBlock()) | 77 if (current.IsLayoutBlock()) |
82 return current; | 78 return current; |
83 if (!current.IsLayoutInline() || current.IsRubyText()) | 79 if (!current.IsLayoutInline() || current.IsRubyText()) |
84 return nullptr; | 80 return nullptr; |
85 | 81 |
86 const ComputedStyle& style_to_use = current.StyleRef(first_line); | 82 const ComputedStyle& style_to_use = current.StyleRef(first_line); |
87 if (style_to_use.GetTextDecoration() & kTextDecorationUnderline) | 83 if (style_to_use.GetTextDecoration() & kTextDecorationUnderline) |
88 return current; | 84 return current; |
89 | 85 |
90 current = current.Parent(); | 86 current = current.Parent(); |
91 if (!current) | 87 if (!current) |
92 return current; | 88 return current; |
93 | 89 |
94 if (Node* node = current.GetNode()) { | 90 if (Node* node = current.GetNode()) { |
95 if (isHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag)) | 91 if (isHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag)) |
96 return current; | 92 return current; |
97 } | 93 } |
98 } | 94 } |
99 } | 95 } |
100 | 96 |
101 static int ComputeUnderlineOffsetForUnder(const ComputedStyle& style, | 97 static int ComputeUnderlineOffsetForUnder( |
102 const InlineTextBox* inline_text_box, | 98 const ComputedStyle& style, |
103 bool is_overline = false) { | 99 const InlineTextBox* inline_text_box, |
100 LineLayoutItem decorating_box, | |
101 float text_decoration_thickness, | |
102 LineVerticalPositionType position_type) { | |
104 const RootInlineBox& root = inline_text_box->Root(); | 103 const RootInlineBox& root = inline_text_box->Root(); |
105 LineLayoutItem decoration_object = EnclosingUnderlineObject(inline_text_box); | 104 FontBaseline baseline_type = root.BaselineType(); |
106 LayoutUnit offset; | 105 LayoutUnit offset = inline_text_box->OffsetTo(position_type, baseline_type); |
107 if (style.IsFlippedLinesWritingMode()) { | |
108 LayoutUnit position = inline_text_box->LogicalTop(); | |
109 offset = | |
110 position - root.MinLogicalTopForUnderline(decoration_object, position); | |
111 } else { | |
112 LayoutUnit position = inline_text_box->LogicalBottom(); | |
113 offset = root.MaxLogicalBottomForUnderline(decoration_object, position) - | |
114 position; | |
115 } | |
116 if (is_overline) | |
117 return std::min(-offset, LayoutUnit()).ToInt(); | |
118 return (inline_text_box->LogicalHeight() + std::max(offset, LayoutUnit())) | |
119 .ToInt(); | |
120 } | |
121 | 106 |
122 static int ComputeOverlineOffset(const ComputedStyle& style, | 107 // Compute offset to the farthest position of the decorating box. |
123 const InlineTextBox* inline_text_box) { | 108 LayoutUnit logical_top = inline_text_box->LogicalTop(); |
124 return ComputeUnderlineOffsetForUnder(style, inline_text_box, true); | 109 LayoutUnit position = logical_top + offset; |
110 LayoutUnit farthest = root.FarthestPositionForUnderline( | |
111 decorating_box, position_type, baseline_type, position); | |
112 int offset_int = (farthest - logical_top).ToInt(); | |
eae
2017/05/01 16:21:48
Is flooring the desired behavior here? If so pleas
kojii
2017/05/02 22:56:52
Tested Round() and Floor() but Floor() looks bette
| |
113 | |
114 // Gaps are not needed for TextTop because it generally has internal | |
115 // leadings. | |
116 if (position_type == LineVerticalPositionType::TextTop) | |
117 return offset_int; | |
118 return !IsOverSide(position_type) ? offset_int + 1 : offset_int - 1; | |
125 } | 119 } |
126 | 120 |
127 static int ComputeUnderlineOffsetForRoman( | 121 static int ComputeUnderlineOffsetForRoman( |
128 const FontMetrics& font_metrics, | 122 const FontMetrics& font_metrics, |
129 const float text_decoration_thickness) { | 123 const float text_decoration_thickness) { |
130 // Compute the gap between the font and the underline. Use at least one | 124 // Compute the gap between the font and the underline. Use at least one |
131 // pixel gap, if underline is thick then use a bigger gap. | 125 // pixel gap, if underline is thick then use a bigger gap. |
132 int gap = 0; | 126 int gap = 0; |
133 | 127 |
134 // Underline position of zero means draw underline on Baseline Position, | 128 // Underline position of zero means draw underline on Baseline Position, |
135 // in Blink we need at least 1-pixel gap to adding following check. | 129 // in Blink we need at least 1-pixel gap to adding following check. |
136 // Positive underline Position means underline should be drawn above baseline | 130 // Positive underline Position means underline should be drawn above baseline |
137 // and negative value means drawing below baseline, negating the value as in | 131 // and negative value means drawing below baseline, negating the value as in |
138 // Blink downward Y-increases. | 132 // Blink downward Y-increases. |
139 | 133 |
140 if (font_metrics.UnderlinePosition()) | 134 if (font_metrics.UnderlinePosition()) |
141 gap = -font_metrics.UnderlinePosition(); | 135 gap = -font_metrics.UnderlinePosition(); |
142 else | 136 else |
143 gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f)); | 137 gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f)); |
144 | 138 |
145 // Position underline near the alphabetic baseline. | 139 // Position underline near the alphabetic baseline. |
146 return font_metrics.Ascent() + gap; | 140 return font_metrics.Ascent() + gap; |
147 } | 141 } |
148 | 142 |
149 static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, | 143 static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, |
150 const ComputedStyle& style, | 144 const ComputedStyle& style, |
151 const FontMetrics& font_metrics, | 145 const FontMetrics& font_metrics, |
152 const InlineTextBox* inline_text_box, | 146 const InlineTextBox* inline_text_box, |
147 LineLayoutItem decorating_box, | |
153 const float text_decoration_thickness) { | 148 const float text_decoration_thickness) { |
154 switch (underline_position) { | 149 switch (underline_position) { |
155 default: | 150 default: |
156 NOTREACHED(); | 151 NOTREACHED(); |
157 // Fall through. | 152 // Fall through. |
158 case ResolvedUnderlinePosition::kRoman: | 153 case ResolvedUnderlinePosition::kRoman: |
159 return ComputeUnderlineOffsetForRoman(font_metrics, | 154 return ComputeUnderlineOffsetForRoman(font_metrics, |
160 text_decoration_thickness); | 155 text_decoration_thickness); |
161 case ResolvedUnderlinePosition::kUnder: | 156 case ResolvedUnderlinePosition::kUnder: |
162 // Position underline at the under edge of the lowest element's | 157 // Position underline at the under edge of the lowest element's |
163 // content box. | 158 // content box. |
164 return ComputeUnderlineOffsetForUnder(style, inline_text_box); | 159 return ComputeUnderlineOffsetForUnder( |
160 style, inline_text_box, decorating_box, text_decoration_thickness, | |
161 LineVerticalPositionType::BottomOfEmHeight); | |
165 } | 162 } |
166 } | 163 } |
167 | 164 |
168 static bool ShouldSetDecorationAntialias( | 165 static bool ShouldSetDecorationAntialias( |
169 const Vector<AppliedTextDecoration>& decorations) { | 166 const Vector<AppliedTextDecoration>& decorations) { |
170 for (const AppliedTextDecoration& decoration : decorations) { | 167 for (const AppliedTextDecoration& decoration : decorations) { |
171 TextDecorationStyle decoration_style = decoration.Style(); | 168 TextDecorationStyle decoration_style = decoration.Style(); |
172 if (decoration_style == kTextDecorationStyleDotted || | 169 if (decoration_style == kTextDecorationStyleDotted || |
173 decoration_style == kTextDecorationStyleDashed) | 170 decoration_style == kTextDecorationStyleDashed) |
174 return true; | 171 return true; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 STACK_ALLOCATED(); | 223 STACK_ALLOCATED(); |
227 | 224 |
228 LayoutUnit width; | 225 LayoutUnit width; |
229 FloatPoint local_origin; | 226 FloatPoint local_origin; |
230 bool antialias; | 227 bool antialias; |
231 float baseline; | 228 float baseline; |
232 const ComputedStyle* style; | 229 const ComputedStyle* style; |
233 const SimpleFontData* font_data; | 230 const SimpleFontData* font_data; |
234 float thickness; | 231 float thickness; |
235 float double_offset; | 232 float double_offset; |
233 FontBaseline baseline_type; | |
234 ResolvedUnderlinePosition underline_position; | |
235 // Decorating box: https://drafts.csswg.org/css-text-decor-3/#decorating-box | |
236 LineLayoutItem decorating_box; | |
236 }; | 237 }; |
237 | 238 |
238 class AppliedDecorationPainter final { | 239 class AppliedDecorationPainter final { |
239 STACK_ALLOCATED(); | 240 STACK_ALLOCATED(); |
240 | 241 |
241 public: | 242 public: |
242 AppliedDecorationPainter(GraphicsContext& context, | 243 AppliedDecorationPainter(GraphicsContext& context, |
243 const DecorationInfo& decoration_info, | 244 const DecorationInfo& decoration_info, |
244 float start_point_y_offset, | 245 float start_point_y_offset, |
245 const AppliedTextDecoration& decoration, | 246 const AppliedTextDecoration& decoration, |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 | 503 |
503 static void RestoreContextFromDecoration(GraphicsContext& context, | 504 static void RestoreContextFromDecoration(GraphicsContext& context, |
504 const LayoutTextCombine* combined_text, | 505 const LayoutTextCombine* combined_text, |
505 const LayoutRect& box_rect) { | 506 const LayoutRect& box_rect) { |
506 if (combined_text) { | 507 if (combined_text) { |
507 context.ConcatCTM( | 508 context.ConcatCTM( |
508 TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); | 509 TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); |
509 } | 510 } |
510 } | 511 } |
511 | 512 |
513 static float ComputeDecorationThickness(const ComputedStyle* style, | |
514 const SimpleFontData* font_data) { | |
515 // Set the thick of the line to be 10% (or something else ?)of the computed | |
516 // font size and not less than 1px. Using computedFontSize should take care | |
517 // of zoom as well. | |
518 | |
519 // Update Underline thickness, in case we have Faulty Font Metrics calculating | |
520 // underline thickness by old method. | |
521 float text_decoration_thickness = 0.0; | |
522 int font_height_int = 0; | |
523 if (font_data) { | |
524 text_decoration_thickness = | |
525 font_data->GetFontMetrics().UnderlineThickness(); | |
526 font_height_int = (int)(font_data->GetFontMetrics().FloatHeight() + 0.5); | |
eae
2017/05/01 16:21:48
Please add a comment explaining this logic (especi
kojii
2017/05/02 22:56:52
Done, didn't pay much attention when I moved this
| |
527 } | |
528 if ((text_decoration_thickness == 0.f) || | |
529 (text_decoration_thickness >= (font_height_int >> 1))) { | |
530 text_decoration_thickness = std::max(1.f, style->ComputedFontSize() / 10.f); | |
531 } | |
532 return text_decoration_thickness; | |
533 } | |
534 | |
512 static void ComputeDecorationInfo( | 535 static void ComputeDecorationInfo( |
513 DecorationInfo& decoration_info, | 536 DecorationInfo& decoration_info, |
514 const InlineTextBox& box, | 537 const InlineTextBox& box, |
515 const LayoutPoint& box_origin, | 538 const LayoutPoint& box_origin, |
516 const Vector<AppliedTextDecoration>& decorations) { | 539 const Vector<AppliedTextDecoration>& decorations) { |
517 LayoutPoint local_origin = LayoutPoint(box_origin); | 540 LayoutPoint local_origin = LayoutPoint(box_origin); |
518 LayoutUnit width = box.LogicalWidth(); | 541 LayoutUnit width = box.LogicalWidth(); |
519 if (box.Truncation() != kCNoTruncation) { | 542 if (box.Truncation() != kCNoTruncation) { |
520 bool ltr = box.IsLeftToRightDirection(); | 543 bool ltr = box.IsLeftToRightDirection(); |
521 bool flow_is_ltr = | 544 bool flow_is_ltr = |
522 box.GetLineLayoutItem().Style()->IsLeftToRightDirection(); | 545 box.GetLineLayoutItem().Style()->IsLeftToRightDirection(); |
523 width = LayoutUnit(box.GetLineLayoutItem().Width( | 546 width = LayoutUnit(box.GetLineLayoutItem().Width( |
524 ltr == flow_is_ltr ? box.Start() : box.Start() + box.Truncation(), | 547 ltr == flow_is_ltr ? box.Start() : box.Start() + box.Truncation(), |
525 ltr == flow_is_ltr ? box.Truncation() : box.Len() - box.Truncation(), | 548 ltr == flow_is_ltr ? box.Truncation() : box.Len() - box.Truncation(), |
526 box.TextPos(), flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, | 549 box.TextPos(), flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, |
527 box.IsFirstLineStyle())); | 550 box.IsFirstLineStyle())); |
528 if (!flow_is_ltr) { | 551 if (!flow_is_ltr) { |
529 local_origin.Move(box.LogicalWidth() - width, LayoutUnit()); | 552 local_origin.Move(box.LogicalWidth() - width, LayoutUnit()); |
530 } | 553 } |
531 } | 554 } |
532 decoration_info.width = width; | 555 decoration_info.width = width; |
533 decoration_info.local_origin = FloatPoint(local_origin); | 556 decoration_info.local_origin = FloatPoint(local_origin); |
534 | 557 |
535 decoration_info.antialias = ShouldSetDecorationAntialias(decorations); | 558 decoration_info.antialias = ShouldSetDecorationAntialias(decorations); |
536 | 559 |
537 decoration_info.style = | 560 decoration_info.style = |
538 LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) | 561 LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) |
539 ->Style(box.IsFirstLineStyle()); | 562 ->Style(box.IsFirstLineStyle()); |
563 decoration_info.baseline_type = box.Root().BaselineType(); | |
564 decoration_info.underline_position = ResolveUnderlinePosition( | |
565 *decoration_info.style, decoration_info.baseline_type); | |
566 | |
540 decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); | 567 decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); |
541 DCHECK(decoration_info.font_data); | 568 DCHECK(decoration_info.font_data); |
542 decoration_info.baseline = | 569 decoration_info.baseline = |
543 decoration_info.font_data | 570 decoration_info.font_data |
544 ? decoration_info.font_data->GetFontMetrics().FloatAscent() | 571 ? decoration_info.font_data->GetFontMetrics().FloatAscent() |
545 : 0; | 572 : 0; |
546 | 573 |
547 // Set the thick of the line to be 10% (or something else ?)of the computed | 574 if (decoration_info.underline_position == ResolvedUnderlinePosition::kRoman) { |
548 // font size and not less than 1px. Using computedFontSize should take care | 575 decoration_info.thickness = ComputeDecorationThickness( |
549 // of zoom as well. | 576 decoration_info.style, decoration_info.font_data); |
550 | 577 } else { |
551 // Update Underline thickness, in case we have Faulty Font Metrics calculating | 578 // Compute decorating box. Position and thickness are computed from the |
552 // underline thickness by old method. | 579 // decorating box. |
553 float text_decoration_thickness = 0.0; | 580 // Only for non-Roman for now for the performance implications. |
554 int font_height_int = 0; | 581 // https:// drafts.csswg.org/css-text-decor-3/#decorating-box |
555 if (decoration_info.font_data) { | 582 decoration_info.decorating_box = EnclosingUnderlineObject(&box); |
556 text_decoration_thickness = | 583 if (decoration_info.decorating_box) { |
557 decoration_info.font_data->GetFontMetrics().UnderlineThickness(); | 584 decoration_info.thickness = ComputeDecorationThickness( |
558 font_height_int = | 585 decoration_info.decorating_box.Style(), |
559 (int)(decoration_info.font_data->GetFontMetrics().FloatHeight() + 0.5); | 586 decoration_info.decorating_box.Style()->GetFont().PrimaryFont()); |
587 } else { | |
588 decoration_info.thickness = ComputeDecorationThickness( | |
589 decoration_info.style, decoration_info.font_data); | |
590 } | |
560 } | 591 } |
561 if ((text_decoration_thickness == 0.f) || | |
562 (text_decoration_thickness >= (font_height_int >> 1))) { | |
563 text_decoration_thickness = | |
564 std::max(1.f, decoration_info.style->ComputedFontSize() / 10.f); | |
565 } | |
566 decoration_info.thickness = text_decoration_thickness; | |
567 | 592 |
568 // Offset between lines - always non-zero, so lines never cross each other. | 593 // Offset between lines - always non-zero, so lines never cross each other. |
569 decoration_info.double_offset = text_decoration_thickness + 1.f; | 594 decoration_info.double_offset = decoration_info.thickness + 1.f; |
570 } | 595 } |
571 | 596 |
572 static void PaintDecorationsExceptLineThrough( | 597 static void PaintDecorationsExceptLineThrough( |
573 TextPainter& text_painter, | 598 TextPainter& text_painter, |
574 bool& has_line_through_decoration, | 599 bool& has_line_through_decoration, |
575 const InlineTextBox& box, | 600 const InlineTextBox& box, |
576 const DecorationInfo& decoration_info, | 601 const DecorationInfo& decoration_info, |
577 const PaintInfo& paint_info, | 602 const PaintInfo& paint_info, |
578 const Vector<AppliedTextDecoration>& decorations) { | 603 const Vector<AppliedTextDecoration>& decorations) { |
579 GraphicsContext& context = paint_info.context; | 604 GraphicsContext& context = paint_info.context; |
580 GraphicsContextStateSaver state_saver(context); | 605 GraphicsContextStateSaver state_saver(context); |
581 context.SetStrokeThickness(decoration_info.thickness); | 606 context.SetStrokeThickness(decoration_info.thickness); |
582 bool skip_intercepts = | 607 bool skip_intercepts = |
583 decoration_info.style->GetTextDecorationSkip() & kTextDecorationSkipInk; | 608 decoration_info.style->GetTextDecorationSkip() & kTextDecorationSkipInk; |
584 | 609 |
585 // text-underline-position may flip underline and overline. | 610 // text-underline-position may flip underline and overline. |
586 ResolvedUnderlinePosition underline_position = | 611 ResolvedUnderlinePosition underline_position = |
587 ResolveUnderlinePosition(*decoration_info.style, &box); | 612 decoration_info.underline_position; |
588 bool flip_underline_and_overline = false; | 613 bool flip_underline_and_overline = false; |
589 if (underline_position == ResolvedUnderlinePosition::kOver) { | 614 if (underline_position == ResolvedUnderlinePosition::kOver) { |
590 flip_underline_and_overline = true; | 615 flip_underline_and_overline = true; |
591 underline_position = ResolvedUnderlinePosition::kUnder; | 616 underline_position = ResolvedUnderlinePosition::kUnder; |
592 } | 617 } |
593 | 618 |
594 for (const AppliedTextDecoration& decoration : decorations) { | 619 for (const AppliedTextDecoration& decoration : decorations) { |
595 TextDecoration lines = decoration.Lines(); | 620 TextDecoration lines = decoration.Lines(); |
596 if (flip_underline_and_overline) { | 621 if (flip_underline_and_overline) { |
597 lines = static_cast<TextDecoration>( | 622 lines = static_cast<TextDecoration>( |
598 lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); | 623 lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); |
599 } | 624 } |
600 if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { | 625 if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { |
601 const int underline_offset = | 626 const int underline_offset = ComputeUnderlineOffset( |
602 ComputeUnderlineOffset(underline_position, *decoration_info.style, | 627 underline_position, *decoration_info.style, |
603 decoration_info.font_data->GetFontMetrics(), | 628 decoration_info.font_data->GetFontMetrics(), &box, |
604 &box, decoration_info.thickness); | 629 decoration_info.decorating_box, decoration_info.thickness); |
605 AppliedDecorationPainter decoration_painter( | 630 AppliedDecorationPainter decoration_painter( |
606 context, decoration_info, underline_offset, decoration, | 631 context, decoration_info, underline_offset, decoration, |
607 decoration_info.double_offset, 1); | 632 decoration_info.double_offset, 1); |
608 if (skip_intercepts) { | 633 if (skip_intercepts) { |
609 text_painter.ClipDecorationsStripe( | 634 text_painter.ClipDecorationsStripe( |
610 -decoration_info.baseline + | 635 -decoration_info.baseline + |
611 decoration_painter.DecorationBounds().Y() - | 636 decoration_painter.DecorationBounds().Y() - |
612 decoration_info.local_origin.Y(), | 637 decoration_info.local_origin.Y(), |
613 decoration_painter.DecorationBounds().Height(), | 638 decoration_painter.DecorationBounds().Height(), |
614 decoration_info.thickness); | 639 decoration_info.thickness); |
615 } | 640 } |
616 decoration_painter.Paint(); | 641 decoration_painter.Paint(); |
617 } | 642 } |
618 if (lines & kTextDecorationOverline) { | 643 if (lines & kTextDecorationOverline) { |
619 const int overline_offset = | 644 const int overline_offset = ComputeUnderlineOffsetForUnder( |
620 ComputeOverlineOffset(*decoration_info.style, &box); | 645 *decoration_info.style, &box, decoration_info.decorating_box, |
646 decoration_info.thickness, | |
647 flip_underline_and_overline ? LineVerticalPositionType::TopOfEmHeight | |
648 : LineVerticalPositionType::TextTop); | |
621 AppliedDecorationPainter decoration_painter( | 649 AppliedDecorationPainter decoration_painter( |
622 context, decoration_info, overline_offset, decoration, | 650 context, decoration_info, overline_offset, decoration, |
623 -decoration_info.double_offset, 1); | 651 -decoration_info.double_offset, 1); |
624 if (skip_intercepts) { | 652 if (skip_intercepts) { |
625 text_painter.ClipDecorationsStripe( | 653 text_painter.ClipDecorationsStripe( |
626 -decoration_info.baseline + | 654 -decoration_info.baseline + |
627 decoration_painter.DecorationBounds().Y() - | 655 decoration_painter.DecorationBounds().Y() - |
628 decoration_info.local_origin.Y(), | 656 decoration_info.local_origin.Y(), |
629 decoration_painter.DecorationBounds().Height(), | 657 decoration_painter.DecorationBounds().Height(), |
630 decoration_info.thickness); | 658 decoration_info.thickness); |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1571 | 1599 |
1572 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), | 1600 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), |
1573 inline_text_box_.LogicalHeight())); | 1601 inline_text_box_.LogicalHeight())); |
1574 context.Clip(FloatRect(box_rect)); | 1602 context.Clip(FloatRect(box_rect)); |
1575 context.DrawHighlightForText(font, run, FloatPoint(box_origin), | 1603 context.DrawHighlightForText(font, run, FloatPoint(box_origin), |
1576 box_rect.Height().ToInt(), color, | 1604 box_rect.Height().ToInt(), color, |
1577 paint_offsets.first, paint_offsets.second); | 1605 paint_offsets.first, paint_offsets.second); |
1578 } | 1606 } |
1579 | 1607 |
1580 } // namespace blink | 1608 } // namespace blink |
OLD | NEW |