Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| index 4b6758b652afb09d329f60794ed9155051a1dcb7..8e5f5d4d145949947e02ed30a107cd98f79cbb25 100644 |
| --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| @@ -43,20 +43,14 @@ enum class ResolvedUnderlinePosition { kRoman, kUnder, kOver }; |
| static ResolvedUnderlinePosition ResolveUnderlinePosition( |
| const ComputedStyle& style, |
| - const InlineTextBox* inline_text_box) { |
| + FontBaseline baseline_type) { |
| // |auto| should resolve to |under| to avoid drawing through glyphs in |
| // scripts where it would not be appropriate (e.g., ideographs.) |
| // However, this has performance implications. For now, we only work with |
| // vertical text. |
| - switch (inline_text_box->Root().BaselineType()) { |
| - default: |
| - NOTREACHED(); |
| - // Fall though. |
| + switch (baseline_type) { |
| case kAlphabeticBaseline: |
| switch (style.GetTextUnderlinePosition()) { |
| - default: |
| - NOTREACHED(); |
| - // Fall though. |
| case kTextUnderlinePositionAuto: |
| return ResolvedUnderlinePosition::kRoman; |
| case kTextUnderlinePositionUnder: |
| @@ -71,6 +65,8 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition( |
| return ResolvedUnderlinePosition::kOver; |
| return ResolvedUnderlinePosition::kUnder; |
| } |
| + NOTREACHED(); |
| + return ResolvedUnderlinePosition::kRoman; |
| } |
| static LineLayoutItem EnclosingUnderlineObject( |
| @@ -98,30 +94,28 @@ static LineLayoutItem EnclosingUnderlineObject( |
| } |
| } |
| -static int ComputeUnderlineOffsetForUnder(const ComputedStyle& style, |
| - const InlineTextBox* inline_text_box, |
| - bool is_overline = false) { |
| +static int ComputeUnderlineOffsetForUnder( |
| + const ComputedStyle& style, |
| + const InlineTextBox* inline_text_box, |
| + LineLayoutItem decorating_box, |
| + float text_decoration_thickness, |
| + LineVerticalPositionType position_type) { |
| const RootInlineBox& root = inline_text_box->Root(); |
| - LineLayoutItem decoration_object = EnclosingUnderlineObject(inline_text_box); |
| - LayoutUnit offset; |
| - if (style.IsFlippedLinesWritingMode()) { |
| - LayoutUnit position = inline_text_box->LogicalTop(); |
| - offset = |
| - position - root.MinLogicalTopForUnderline(decoration_object, position); |
| - } else { |
| - LayoutUnit position = inline_text_box->LogicalBottom(); |
| - offset = root.MaxLogicalBottomForUnderline(decoration_object, position) - |
| - position; |
| - } |
| - if (is_overline) |
| - return std::min(-offset, LayoutUnit()).ToInt(); |
| - return (inline_text_box->LogicalHeight() + std::max(offset, LayoutUnit())) |
| - .ToInt(); |
| -} |
| - |
| -static int ComputeOverlineOffset(const ComputedStyle& style, |
| - const InlineTextBox* inline_text_box) { |
| - return ComputeUnderlineOffsetForUnder(style, inline_text_box, true); |
| + FontBaseline baseline_type = root.BaselineType(); |
| + LayoutUnit offset = inline_text_box->OffsetTo(position_type, baseline_type); |
| + |
| + // Compute offset to the farthest position of the decorating box. |
| + LayoutUnit logical_top = inline_text_box->LogicalTop(); |
| + LayoutUnit position = logical_top + offset; |
| + LayoutUnit farthest = root.FarthestPositionForUnderline( |
| + decorating_box, position_type, baseline_type, position); |
| + 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
|
| + |
| + // Gaps are not needed for TextTop because it generally has internal |
| + // leadings. |
| + if (position_type == LineVerticalPositionType::TextTop) |
| + return offset_int; |
| + return !IsOverSide(position_type) ? offset_int + 1 : offset_int - 1; |
| } |
| static int ComputeUnderlineOffsetForRoman( |
| @@ -150,6 +144,7 @@ static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, |
| const ComputedStyle& style, |
| const FontMetrics& font_metrics, |
| const InlineTextBox* inline_text_box, |
| + LineLayoutItem decorating_box, |
| const float text_decoration_thickness) { |
| switch (underline_position) { |
| default: |
| @@ -161,7 +156,9 @@ static int ComputeUnderlineOffset(ResolvedUnderlinePosition underline_position, |
| case ResolvedUnderlinePosition::kUnder: |
| // Position underline at the under edge of the lowest element's |
| // content box. |
| - return ComputeUnderlineOffsetForUnder(style, inline_text_box); |
| + return ComputeUnderlineOffsetForUnder( |
| + style, inline_text_box, decorating_box, text_decoration_thickness, |
| + LineVerticalPositionType::BottomOfEmHeight); |
| } |
| } |
| @@ -233,6 +230,10 @@ struct DecorationInfo final { |
| const SimpleFontData* font_data; |
| float thickness; |
| float double_offset; |
| + FontBaseline baseline_type; |
| + ResolvedUnderlinePosition underline_position; |
| + // Decorating box: https://drafts.csswg.org/css-text-decor-3/#decorating-box |
| + LineLayoutItem decorating_box; |
| }; |
| class AppliedDecorationPainter final { |
| @@ -509,6 +510,28 @@ static void RestoreContextFromDecoration(GraphicsContext& context, |
| } |
| } |
| +static float ComputeDecorationThickness(const ComputedStyle* style, |
| + const SimpleFontData* font_data) { |
| + // Set the thick of the line to be 10% (or something else ?)of the computed |
| + // font size and not less than 1px. Using computedFontSize should take care |
| + // of zoom as well. |
| + |
| + // Update Underline thickness, in case we have Faulty Font Metrics calculating |
| + // underline thickness by old method. |
| + float text_decoration_thickness = 0.0; |
| + int font_height_int = 0; |
| + if (font_data) { |
| + text_decoration_thickness = |
| + font_data->GetFontMetrics().UnderlineThickness(); |
| + 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
|
| + } |
| + if ((text_decoration_thickness == 0.f) || |
| + (text_decoration_thickness >= (font_height_int >> 1))) { |
| + text_decoration_thickness = std::max(1.f, style->ComputedFontSize() / 10.f); |
| + } |
| + return text_decoration_thickness; |
| +} |
| + |
| static void ComputeDecorationInfo( |
| DecorationInfo& decoration_info, |
| const InlineTextBox& box, |
| @@ -537,6 +560,10 @@ static void ComputeDecorationInfo( |
| decoration_info.style = |
| LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) |
| ->Style(box.IsFirstLineStyle()); |
| + decoration_info.baseline_type = box.Root().BaselineType(); |
| + decoration_info.underline_position = ResolveUnderlinePosition( |
| + *decoration_info.style, decoration_info.baseline_type); |
| + |
| decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); |
| DCHECK(decoration_info.font_data); |
| decoration_info.baseline = |
| @@ -544,29 +571,27 @@ static void ComputeDecorationInfo( |
| ? decoration_info.font_data->GetFontMetrics().FloatAscent() |
| : 0; |
| - // Set the thick of the line to be 10% (or something else ?)of the computed |
| - // font size and not less than 1px. Using computedFontSize should take care |
| - // of zoom as well. |
| - |
| - // Update Underline thickness, in case we have Faulty Font Metrics calculating |
| - // underline thickness by old method. |
| - float text_decoration_thickness = 0.0; |
| - int font_height_int = 0; |
| - if (decoration_info.font_data) { |
| - text_decoration_thickness = |
| - decoration_info.font_data->GetFontMetrics().UnderlineThickness(); |
| - font_height_int = |
| - (int)(decoration_info.font_data->GetFontMetrics().FloatHeight() + 0.5); |
| - } |
| - if ((text_decoration_thickness == 0.f) || |
| - (text_decoration_thickness >= (font_height_int >> 1))) { |
| - text_decoration_thickness = |
| - std::max(1.f, decoration_info.style->ComputedFontSize() / 10.f); |
| + if (decoration_info.underline_position == ResolvedUnderlinePosition::kRoman) { |
| + decoration_info.thickness = ComputeDecorationThickness( |
| + decoration_info.style, decoration_info.font_data); |
| + } else { |
| + // Compute decorating box. Position and thickness are computed from the |
| + // decorating box. |
| + // Only for non-Roman for now for the performance implications. |
| + // https:// drafts.csswg.org/css-text-decor-3/#decorating-box |
| + decoration_info.decorating_box = EnclosingUnderlineObject(&box); |
| + if (decoration_info.decorating_box) { |
| + decoration_info.thickness = ComputeDecorationThickness( |
| + decoration_info.decorating_box.Style(), |
| + decoration_info.decorating_box.Style()->GetFont().PrimaryFont()); |
| + } else { |
| + decoration_info.thickness = ComputeDecorationThickness( |
| + decoration_info.style, decoration_info.font_data); |
| + } |
| } |
| - decoration_info.thickness = text_decoration_thickness; |
| // Offset between lines - always non-zero, so lines never cross each other. |
| - decoration_info.double_offset = text_decoration_thickness + 1.f; |
| + decoration_info.double_offset = decoration_info.thickness + 1.f; |
| } |
| static void PaintDecorationsExceptLineThrough( |
| @@ -584,7 +609,7 @@ static void PaintDecorationsExceptLineThrough( |
| // text-underline-position may flip underline and overline. |
| ResolvedUnderlinePosition underline_position = |
| - ResolveUnderlinePosition(*decoration_info.style, &box); |
| + decoration_info.underline_position; |
| bool flip_underline_and_overline = false; |
| if (underline_position == ResolvedUnderlinePosition::kOver) { |
| flip_underline_and_overline = true; |
| @@ -598,10 +623,10 @@ static void PaintDecorationsExceptLineThrough( |
| lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); |
| } |
| if ((lines & kTextDecorationUnderline) && decoration_info.font_data) { |
| - const int underline_offset = |
| - ComputeUnderlineOffset(underline_position, *decoration_info.style, |
| - decoration_info.font_data->GetFontMetrics(), |
| - &box, decoration_info.thickness); |
| + const int underline_offset = ComputeUnderlineOffset( |
| + underline_position, *decoration_info.style, |
| + decoration_info.font_data->GetFontMetrics(), &box, |
| + decoration_info.decorating_box, decoration_info.thickness); |
| AppliedDecorationPainter decoration_painter( |
| context, decoration_info, underline_offset, decoration, |
| decoration_info.double_offset, 1); |
| @@ -616,8 +641,11 @@ static void PaintDecorationsExceptLineThrough( |
| decoration_painter.Paint(); |
| } |
| if (lines & kTextDecorationOverline) { |
| - const int overline_offset = |
| - ComputeOverlineOffset(*decoration_info.style, &box); |
| + const int overline_offset = ComputeUnderlineOffsetForUnder( |
| + *decoration_info.style, &box, decoration_info.decorating_box, |
| + decoration_info.thickness, |
| + flip_underline_and_overline ? LineVerticalPositionType::TopOfEmHeight |
| + : LineVerticalPositionType::TextTop); |
| AppliedDecorationPainter decoration_painter( |
| context, decoration_info, overline_offset, decoration, |
| -decoration_info.double_offset, 1); |