| 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 // Round() looks more logical but Floor() produces better results in |
| 113 // positive/negative offsets, in horizontal/vertical flows, on Win/Mac/Linux. |
| 114 int offset_int = (farthest - logical_top).Floor(); |
| 115 |
| 116 // Gaps are not needed for TextTop because it generally has internal |
| 117 // leadings. |
| 118 if (position_type == LineVerticalPositionType::TextTop) |
| 119 return offset_int; |
| 120 return !IsLineOverSide(position_type) ? offset_int + 1 : offset_int - 1; |
| 125 } | 121 } |
| 126 | 122 |
| 127 static int ComputeUnderlineOffsetForRoman( | 123 static int ComputeUnderlineOffsetForRoman( |
| 128 const FontMetrics& font_metrics, | 124 const FontMetrics& font_metrics, |
| 129 const float text_decoration_thickness) { | 125 const float text_decoration_thickness) { |
| 130 // Compute the gap between the font and the underline. Use at least one | 126 // 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. | 127 // pixel gap, if underline is thick then use a bigger gap. |
| 132 int gap = 0; | 128 int gap = 0; |
| 133 | 129 |
| 134 // Underline position of zero means draw underline on Baseline Position, | 130 // Underline position of zero means draw underline on Baseline Position, |
| 135 // in Blink we need at least 1-pixel gap to adding following check. | 131 // in Blink we need at least 1-pixel gap to adding following check. |
| 136 // Positive underline Position means underline should be drawn above baseline | 132 // Positive underline Position means underline should be drawn above baseline |
| 137 // and negative value means drawing below baseline, negating the value as in | 133 // and negative value means drawing below baseline, negating the value as in |
| 138 // Blink downward Y-increases. | 134 // Blink downward Y-increases. |
| 139 | 135 |
| 140 if (font_metrics.UnderlinePosition()) | 136 if (font_metrics.UnderlinePosition()) |
| 141 gap = -font_metrics.UnderlinePosition(); | 137 gap = -font_metrics.UnderlinePosition(); |
| 142 else | 138 else |
| 143 gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f)); | 139 gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f)); |
| 144 | 140 |
| 145 // Position underline near the alphabetic baseline. | 141 // Position underline near the alphabetic baseline. |
| 146 return font_metrics.Ascent() + gap; | 142 return font_metrics.Ascent() + gap; |
| 147 } | 143 } |
| 148 | 144 |
| 149 static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, | 145 static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, |
| 150 const ComputedStyle& style, | 146 const ComputedStyle& style, |
| 151 const FontMetrics& font_metrics, | 147 const FontMetrics& font_metrics, |
| 152 const InlineTextBox* inline_text_box, | 148 const InlineTextBox* inline_text_box, |
| 149 LineLayoutItem decorating_box, |
| 153 const float text_decoration_thickness) { | 150 const float text_decoration_thickness) { |
| 154 switch (underline_position) { | 151 switch (underline_position) { |
| 155 default: | 152 default: |
| 156 NOTREACHED(); | 153 NOTREACHED(); |
| 157 // Fall through. | 154 // Fall through. |
| 158 case ResolvedUnderlinePosition::kRoman: | 155 case ResolvedUnderlinePosition::kRoman: |
| 159 return ComputeUnderlineOffsetForRoman(font_metrics, | 156 return ComputeUnderlineOffsetForRoman(font_metrics, |
| 160 text_decoration_thickness); | 157 text_decoration_thickness); |
| 161 case ResolvedUnderlinePosition::kUnder: | 158 case ResolvedUnderlinePosition::kUnder: |
| 162 // Position underline at the under edge of the lowest element's | 159 // Position underline at the under edge of the lowest element's |
| 163 // content box. | 160 // content box. |
| 164 return ComputeUnderlineOffsetForUnder(style, inline_text_box); | 161 return ComputeUnderlineOffsetForUnder( |
| 162 style, inline_text_box, decorating_box, text_decoration_thickness, |
| 163 LineVerticalPositionType::BottomOfEmHeight); |
| 165 } | 164 } |
| 166 } | 165 } |
| 167 | 166 |
| 168 static bool ShouldSetDecorationAntialias( | 167 static bool ShouldSetDecorationAntialias( |
| 169 const Vector<AppliedTextDecoration>& decorations) { | 168 const Vector<AppliedTextDecoration>& decorations) { |
| 170 for (const AppliedTextDecoration& decoration : decorations) { | 169 for (const AppliedTextDecoration& decoration : decorations) { |
| 171 TextDecorationStyle decoration_style = decoration.Style(); | 170 TextDecorationStyle decoration_style = decoration.Style(); |
| 172 if (decoration_style == kTextDecorationStyleDotted || | 171 if (decoration_style == kTextDecorationStyleDotted || |
| 173 decoration_style == kTextDecorationStyleDashed) | 172 decoration_style == kTextDecorationStyleDashed) |
| 174 return true; | 173 return true; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 STACK_ALLOCATED(); | 225 STACK_ALLOCATED(); |
| 227 | 226 |
| 228 LayoutUnit width; | 227 LayoutUnit width; |
| 229 FloatPoint local_origin; | 228 FloatPoint local_origin; |
| 230 bool antialias; | 229 bool antialias; |
| 231 float baseline; | 230 float baseline; |
| 232 const ComputedStyle* style; | 231 const ComputedStyle* style; |
| 233 const SimpleFontData* font_data; | 232 const SimpleFontData* font_data; |
| 234 float thickness; | 233 float thickness; |
| 235 float double_offset; | 234 float double_offset; |
| 235 FontBaseline baseline_type; |
| 236 ResolvedUnderlinePosition underline_position; |
| 237 // Decorating box: https://drafts.csswg.org/css-text-decor-3/#decorating-box |
| 238 LineLayoutItem decorating_box; |
| 236 }; | 239 }; |
| 237 | 240 |
| 238 class AppliedDecorationPainter final { | 241 class AppliedDecorationPainter final { |
| 239 STACK_ALLOCATED(); | 242 STACK_ALLOCATED(); |
| 240 | 243 |
| 241 public: | 244 public: |
| 242 AppliedDecorationPainter(GraphicsContext& context, | 245 AppliedDecorationPainter(GraphicsContext& context, |
| 243 const DecorationInfo& decoration_info, | 246 const DecorationInfo& decoration_info, |
| 244 float start_point_y_offset, | 247 float start_point_y_offset, |
| 245 const AppliedTextDecoration& decoration, | 248 const AppliedTextDecoration& decoration, |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 505 |
| 503 static void RestoreContextFromDecoration(GraphicsContext& context, | 506 static void RestoreContextFromDecoration(GraphicsContext& context, |
| 504 const LayoutTextCombine* combined_text, | 507 const LayoutTextCombine* combined_text, |
| 505 const LayoutRect& box_rect) { | 508 const LayoutRect& box_rect) { |
| 506 if (combined_text) { | 509 if (combined_text) { |
| 507 context.ConcatCTM( | 510 context.ConcatCTM( |
| 508 TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); | 511 TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); |
| 509 } | 512 } |
| 510 } | 513 } |
| 511 | 514 |
| 515 static float ComputeDecorationThickness(const ComputedStyle* style, |
| 516 const SimpleFontData* font_data) { |
| 517 // Set the thick of the line to be 10% (or something else ?)of the computed |
| 518 // font size and not less than 1px. Using computedFontSize should take care |
| 519 // of zoom as well. |
| 520 |
| 521 // Update Underline thickness, in case we have Faulty Font Metrics calculating |
| 522 // underline thickness by old method. |
| 523 float text_decoration_thickness = 0.0; |
| 524 int font_height_int = 0; |
| 525 if (font_data) { |
| 526 text_decoration_thickness = |
| 527 font_data->GetFontMetrics().UnderlineThickness(); |
| 528 font_height_int = font_data->GetFontMetrics().Height(); |
| 529 } |
| 530 if ((text_decoration_thickness == 0.f) || |
| 531 (text_decoration_thickness >= (font_height_int >> 1))) { |
| 532 text_decoration_thickness = std::max(1.f, style->ComputedFontSize() / 10.f); |
| 533 } |
| 534 return text_decoration_thickness; |
| 535 } |
| 536 |
| 512 static void ComputeDecorationInfo( | 537 static void ComputeDecorationInfo( |
| 513 DecorationInfo& decoration_info, | 538 DecorationInfo& decoration_info, |
| 514 const InlineTextBox& box, | 539 const InlineTextBox& box, |
| 515 const LayoutPoint& box_origin, | 540 const LayoutPoint& box_origin, |
| 516 const Vector<AppliedTextDecoration>& decorations) { | 541 const Vector<AppliedTextDecoration>& decorations) { |
| 517 LayoutPoint local_origin = LayoutPoint(box_origin); | 542 LayoutPoint local_origin = LayoutPoint(box_origin); |
| 518 LayoutUnit width = box.LogicalWidth(); | 543 LayoutUnit width = box.LogicalWidth(); |
| 519 if (box.Truncation() != kCNoTruncation) { | 544 if (box.Truncation() != kCNoTruncation) { |
| 520 bool ltr = box.IsLeftToRightDirection(); | 545 bool ltr = box.IsLeftToRightDirection(); |
| 521 bool flow_is_ltr = | 546 bool flow_is_ltr = |
| 522 box.GetLineLayoutItem().Style()->IsLeftToRightDirection(); | 547 box.GetLineLayoutItem().Style()->IsLeftToRightDirection(); |
| 523 width = LayoutUnit(box.GetLineLayoutItem().Width( | 548 width = LayoutUnit(box.GetLineLayoutItem().Width( |
| 524 ltr == flow_is_ltr ? box.Start() : box.Start() + box.Truncation(), | 549 ltr == flow_is_ltr ? box.Start() : box.Start() + box.Truncation(), |
| 525 ltr == flow_is_ltr ? box.Truncation() : box.Len() - box.Truncation(), | 550 ltr == flow_is_ltr ? box.Truncation() : box.Len() - box.Truncation(), |
| 526 box.TextPos(), flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, | 551 box.TextPos(), flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, |
| 527 box.IsFirstLineStyle())); | 552 box.IsFirstLineStyle())); |
| 528 if (!flow_is_ltr) { | 553 if (!flow_is_ltr) { |
| 529 local_origin.Move(box.LogicalWidth() - width, LayoutUnit()); | 554 local_origin.Move(box.LogicalWidth() - width, LayoutUnit()); |
| 530 } | 555 } |
| 531 } | 556 } |
| 532 decoration_info.width = width; | 557 decoration_info.width = width; |
| 533 decoration_info.local_origin = FloatPoint(local_origin); | 558 decoration_info.local_origin = FloatPoint(local_origin); |
| 534 | 559 |
| 535 decoration_info.antialias = ShouldSetDecorationAntialias(decorations); | 560 decoration_info.antialias = ShouldSetDecorationAntialias(decorations); |
| 536 | 561 |
| 537 decoration_info.style = | 562 decoration_info.style = |
| 538 LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) | 563 LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) |
| 539 ->Style(box.IsFirstLineStyle()); | 564 ->Style(box.IsFirstLineStyle()); |
| 565 decoration_info.baseline_type = box.Root().BaselineType(); |
| 566 decoration_info.underline_position = ResolveUnderlinePosition( |
| 567 *decoration_info.style, decoration_info.baseline_type); |
| 568 |
| 540 decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); | 569 decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); |
| 541 DCHECK(decoration_info.font_data); | 570 DCHECK(decoration_info.font_data); |
| 542 decoration_info.baseline = | 571 decoration_info.baseline = |
| 543 decoration_info.font_data | 572 decoration_info.font_data |
| 544 ? decoration_info.font_data->GetFontMetrics().FloatAscent() | 573 ? decoration_info.font_data->GetFontMetrics().FloatAscent() |
| 545 : 0; | 574 : 0; |
| 546 | 575 |
| 547 // Set the thick of the line to be 10% (or something else ?)of the computed | 576 if (decoration_info.underline_position == ResolvedUnderlinePosition::kRoman) { |
| 548 // font size and not less than 1px. Using computedFontSize should take care | 577 decoration_info.thickness = ComputeDecorationThickness( |
| 549 // of zoom as well. | 578 decoration_info.style, decoration_info.font_data); |
| 550 | 579 } else { |
| 551 // Update Underline thickness, in case we have Faulty Font Metrics calculating | 580 // Compute decorating box. Position and thickness are computed from the |
| 552 // underline thickness by old method. | 581 // decorating box. |
| 553 float text_decoration_thickness = 0.0; | 582 // Only for non-Roman for now for the performance implications. |
| 554 int font_height_int = 0; | 583 // https:// drafts.csswg.org/css-text-decor-3/#decorating-box |
| 555 if (decoration_info.font_data) { | 584 decoration_info.decorating_box = EnclosingUnderlineObject(&box); |
| 556 text_decoration_thickness = | 585 if (decoration_info.decorating_box) { |
| 557 decoration_info.font_data->GetFontMetrics().UnderlineThickness(); | 586 decoration_info.thickness = ComputeDecorationThickness( |
| 558 font_height_int = | 587 decoration_info.decorating_box.Style(), |
| 559 (int)(decoration_info.font_data->GetFontMetrics().FloatHeight() + 0.5); | 588 decoration_info.decorating_box.Style()->GetFont().PrimaryFont()); |
| 589 } else { |
| 590 decoration_info.thickness = ComputeDecorationThickness( |
| 591 decoration_info.style, decoration_info.font_data); |
| 592 } |
| 560 } | 593 } |
| 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 | 594 |
| 568 // Offset between lines - always non-zero, so lines never cross each other. | 595 // Offset between lines - always non-zero, so lines never cross each other. |
| 569 decoration_info.double_offset = text_decoration_thickness + 1.f; | 596 decoration_info.double_offset = decoration_info.thickness + 1.f; |
| 570 } | 597 } |
| 571 | 598 |
| 572 static void PaintDecorationsExceptLineThrough( | 599 static void PaintDecorationsExceptLineThrough( |
| 573 TextPainter& text_painter, | 600 TextPainter& text_painter, |
| 574 bool& has_line_through_decoration, | 601 bool& has_line_through_decoration, |
| 575 const InlineTextBox& box, | 602 const InlineTextBox& box, |
| 576 const DecorationInfo& decoration_info, | 603 const DecorationInfo& decoration_info, |
| 577 const PaintInfo& paint_info, | 604 const PaintInfo& paint_info, |
| 578 const Vector<AppliedTextDecoration>& decorations) { | 605 const Vector<AppliedTextDecoration>& decorations) { |
| 579 GraphicsContext& context = paint_info.context; | 606 GraphicsContext& context = paint_info.context; |
| 580 GraphicsContextStateSaver state_saver(context); | 607 GraphicsContextStateSaver state_saver(context); |
| 581 context.SetStrokeThickness(decoration_info.thickness); | 608 context.SetStrokeThickness(decoration_info.thickness); |
| 582 bool skip_intercepts = | 609 bool skip_intercepts = |
| 583 decoration_info.style->GetTextDecorationSkip() & kTextDecorationSkipInk; | 610 decoration_info.style->GetTextDecorationSkip() & kTextDecorationSkipInk; |
| 584 | 611 |
| 585 // text-underline-position may flip underline and overline. | 612 // text-underline-position may flip underline and overline. |
| 586 ResolvedUnderlinePosition underline_position = | 613 ResolvedUnderlinePosition underline_position = |
| 587 ResolveUnderlinePosition(*decoration_info.style, &box); | 614 decoration_info.underline_position; |
| 588 bool flip_underline_and_overline = false; | 615 bool flip_underline_and_overline = false; |
| 589 if (underline_position == ResolvedUnderlinePosition::kOver) { | 616 if (underline_position == ResolvedUnderlinePosition::kOver) { |
| 590 flip_underline_and_overline = true; | 617 flip_underline_and_overline = true; |
| 591 underline_position = ResolvedUnderlinePosition::kUnder; | 618 underline_position = ResolvedUnderlinePosition::kUnder; |
| 592 } | 619 } |
| 593 | 620 |
| 594 for (const AppliedTextDecoration& decoration : decorations) { | 621 for (const AppliedTextDecoration& decoration : decorations) { |
| 595 TextDecoration lines = decoration.Lines(); | 622 TextDecoration lines = decoration.Lines(); |
| 596 if (flip_underline_and_overline) { | 623 if (flip_underline_and_overline) { |
| 597 lines = static_cast<TextDecoration>( | 624 lines = static_cast<TextDecoration>( |
| 598 lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); | 625 lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); |
| 599 } | 626 } |
| 600 if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { | 627 if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { |
| 601 const int underline_offset = | 628 const int underline_offset = ComputeUnderlineOffset( |
| 602 ComputeUnderlineOffset(underline_position, *decoration_info.style, | 629 underline_position, *decoration_info.style, |
| 603 decoration_info.font_data->GetFontMetrics(), | 630 decoration_info.font_data->GetFontMetrics(), &box, |
| 604 &box, decoration_info.thickness); | 631 decoration_info.decorating_box, decoration_info.thickness); |
| 605 AppliedDecorationPainter decoration_painter( | 632 AppliedDecorationPainter decoration_painter( |
| 606 context, decoration_info, underline_offset, decoration, | 633 context, decoration_info, underline_offset, decoration, |
| 607 decoration_info.double_offset, 1); | 634 decoration_info.double_offset, 1); |
| 608 if (skip_intercepts) { | 635 if (skip_intercepts) { |
| 609 text_painter.ClipDecorationsStripe( | 636 text_painter.ClipDecorationsStripe( |
| 610 -decoration_info.baseline + | 637 -decoration_info.baseline + |
| 611 decoration_painter.DecorationBounds().Y() - | 638 decoration_painter.DecorationBounds().Y() - |
| 612 decoration_info.local_origin.Y(), | 639 decoration_info.local_origin.Y(), |
| 613 decoration_painter.DecorationBounds().Height(), | 640 decoration_painter.DecorationBounds().Height(), |
| 614 decoration_info.thickness); | 641 decoration_info.thickness); |
| 615 } | 642 } |
| 616 decoration_painter.Paint(); | 643 decoration_painter.Paint(); |
| 617 } | 644 } |
| 618 if (lines & kTextDecorationOverline) { | 645 if (lines & kTextDecorationOverline) { |
| 619 const int overline_offset = | 646 const int overline_offset = ComputeUnderlineOffsetForUnder( |
| 620 ComputeOverlineOffset(*decoration_info.style, &box); | 647 *decoration_info.style, &box, decoration_info.decorating_box, |
| 648 decoration_info.thickness, |
| 649 flip_underline_and_overline ? LineVerticalPositionType::TopOfEmHeight |
| 650 : LineVerticalPositionType::TextTop); |
| 621 AppliedDecorationPainter decoration_painter( | 651 AppliedDecorationPainter decoration_painter( |
| 622 context, decoration_info, overline_offset, decoration, | 652 context, decoration_info, overline_offset, decoration, |
| 623 -decoration_info.double_offset, 1); | 653 -decoration_info.double_offset, 1); |
| 624 if (skip_intercepts) { | 654 if (skip_intercepts) { |
| 625 text_painter.ClipDecorationsStripe( | 655 text_painter.ClipDecorationsStripe( |
| 626 -decoration_info.baseline + | 656 -decoration_info.baseline + |
| 627 decoration_painter.DecorationBounds().Y() - | 657 decoration_painter.DecorationBounds().Y() - |
| 628 decoration_info.local_origin.Y(), | 658 decoration_info.local_origin.Y(), |
| 629 decoration_painter.DecorationBounds().Height(), | 659 decoration_painter.DecorationBounds().Height(), |
| 630 decoration_info.thickness); | 660 decoration_info.thickness); |
| (...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 | 1601 |
| 1572 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), | 1602 LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(), |
| 1573 inline_text_box_.LogicalHeight())); | 1603 inline_text_box_.LogicalHeight())); |
| 1574 context.Clip(FloatRect(box_rect)); | 1604 context.Clip(FloatRect(box_rect)); |
| 1575 context.DrawHighlightForText(font, run, FloatPoint(box_origin), | 1605 context.DrawHighlightForText(font, run, FloatPoint(box_origin), |
| 1576 box_rect.Height().ToInt(), color, | 1606 box_rect.Height().ToInt(), color, |
| 1577 paint_offsets.first, paint_offsets.second); | 1607 paint_offsets.first, paint_offsets.second); |
| 1578 } | 1608 } |
| 1579 | 1609 |
| 1580 } // namespace blink | 1610 } // namespace blink |
| OLD | NEW |