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 184f9aed920ff27e9f87cfc922135cc25a73eec8..40b8a55e7a51b5aa9db2689e88e3b998c81d8c2e 100644 |
| --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp |
| @@ -216,26 +216,39 @@ static void AdjustStepToDecorationLength(float& step, |
| control_point_distance += adjustment; |
| } |
| +// Holds text decoration painting values to be computed once and subsequently |
| +// use multiple times to handle decoration paint order correctly. See also |
| +// https://www.w3.org/TR/css-text-decor-3/#painting-order |
| +struct DecorationInfo final { |
| + STACK_ALLOCATED(); |
| + |
| + LayoutUnit width; |
| + FloatPoint local_origin; |
| + bool antialias; |
| + float baseline; |
| + const ComputedStyle* style; |
| + const SimpleFontData* font_data; |
| + float thickness; |
| + float double_offset; |
| +}; |
| + |
| class AppliedDecorationPainter final { |
| STACK_ALLOCATED(); |
| public: |
| AppliedDecorationPainter(GraphicsContext& context, |
| - FloatPoint start_point, |
| - float width, |
| + const DecorationInfo& decoration_info, |
| + float start_point_y_offset, |
|
wkorman
2017/04/17 17:57:59
This patch changes this to a float, which preserve
|
| const AppliedTextDecoration& decoration, |
| - float thickness, |
| float double_offset, |
| - int wavy_offset_factor, |
| - bool antialias_decoration) |
| + int wavy_offset_factor) |
| : context_(context), |
| - start_point_(start_point), |
| - width_(width), |
| + start_point_(decoration_info.local_origin + |
| + FloatPoint(0, start_point_y_offset)), |
| + decoration_info_(decoration_info), |
| decoration_(decoration), |
| - thickness_(thickness), |
| double_offset_(double_offset), |
| - wavy_offset_factor_(wavy_offset_factor), |
| - should_antialias_(antialias_decoration){}; |
| + wavy_offset_factor_(wavy_offset_factor){}; |
| void Paint(); |
| FloatRect DecorationBounds(); |
| @@ -247,24 +260,24 @@ class AppliedDecorationPainter final { |
| Path PrepareDottedDashedStrokePath(); |
| GraphicsContext& context_; |
| - FloatPoint start_point_; |
| - float width_; |
| + const FloatPoint start_point_; |
| + const DecorationInfo& decoration_info_; |
| const AppliedTextDecoration& decoration_; |
| - float thickness_; |
| const float double_offset_; |
| const int wavy_offset_factor_; |
| - bool should_antialias_; |
| }; |
| Path AppliedDecorationPainter::PrepareDottedDashedStrokePath() { |
| // These coordinate transforms need to match what's happening in |
| // GraphicsContext's drawLineForText and drawLine. |
| - int y = floorf(start_point_.Y() + std::max<float>(thickness_ / 2.0f, 0.5f)); |
| + int y = floorf(start_point_.Y() + |
| + std::max<float>(decoration_info_.thickness / 2.0f, 0.5f)); |
| Path stroke_path; |
| FloatPoint rounded_start_point(start_point_.X(), y); |
| - FloatPoint rounded_end_point(rounded_start_point + FloatPoint(width_, 0)); |
| + FloatPoint rounded_end_point(rounded_start_point + |
| + FloatPoint(decoration_info_.width, 0)); |
| context_.AdjustLineToPixelBoundaries(rounded_start_point, rounded_end_point, |
| - roundf(thickness_), |
| + roundf(decoration_info_.thickness), |
| context_.GetStrokeStyle()); |
| stroke_path.MoveTo(rounded_start_point); |
| stroke_path.AddLineTo(rounded_end_point); |
| @@ -273,7 +286,7 @@ Path AppliedDecorationPainter::PrepareDottedDashedStrokePath() { |
| FloatRect AppliedDecorationPainter::DecorationBounds() { |
| StrokeData stroke_data; |
| - stroke_data.SetThickness(thickness_); |
| + stroke_data.SetThickness(decoration_info_.thickness); |
| switch (decoration_.Style()) { |
| case kTextDecorationStyleDotted: |
| @@ -289,14 +302,17 @@ FloatRect AppliedDecorationPainter::DecorationBounds() { |
| break; |
| case kTextDecorationStyleDouble: |
| if (double_offset_ > 0) { |
| - return FloatRect(start_point_.X(), start_point_.Y(), width_, |
| - double_offset_ + thickness_); |
| + return FloatRect(start_point_.X(), start_point_.Y(), |
| + decoration_info_.width, |
| + double_offset_ + decoration_info_.thickness); |
| } |
| return FloatRect(start_point_.X(), start_point_.Y() + double_offset_, |
| - width_, -double_offset_ + thickness_); |
| + decoration_info_.width, |
| + -double_offset_ + decoration_info_.thickness); |
| break; |
| case kTextDecorationStyleSolid: |
| - return FloatRect(start_point_.X(), start_point_.Y(), width_, thickness_); |
| + return FloatRect(start_point_.X(), start_point_.Y(), |
| + decoration_info_.width, decoration_info_.thickness); |
| default: |
| break; |
| } |
| @@ -315,14 +331,14 @@ void AppliedDecorationPainter::Paint() { |
| break; |
| case kTextDecorationStyleDotted: |
| case kTextDecorationStyleDashed: |
| - context_.SetShouldAntialias(should_antialias_); |
| + context_.SetShouldAntialias(decoration_info_.antialias); |
| // Fall through |
| default: |
| - context_.DrawLineForText(start_point_, width_); |
| + context_.DrawLineForText(start_point_, decoration_info_.width); |
| if (decoration_.Style() == kTextDecorationStyleDouble) { |
| context_.DrawLineForText(start_point_ + FloatPoint(0, double_offset_), |
| - width_); |
| + decoration_info_.width); |
| } |
| } |
| } |
| @@ -362,10 +378,11 @@ void AppliedDecorationPainter::StrokeWavyTextDecoration() { |
| Path AppliedDecorationPainter::PrepareWavyStrokePath() { |
| FloatPoint p1(start_point_ + |
| FloatPoint(0, double_offset_ * wavy_offset_factor_)); |
| - FloatPoint p2(start_point_ + |
| - FloatPoint(width_, double_offset_ * wavy_offset_factor_)); |
| + FloatPoint p2( |
| + start_point_ + |
| + FloatPoint(decoration_info_.width, double_offset_ * wavy_offset_factor_)); |
| - context_.AdjustLineToPixelBoundaries(p1, p2, thickness_, |
| + context_.AdjustLineToPixelBoundaries(p1, p2, decoration_info_.thickness, |
| context_.GetStrokeStyle()); |
| Path path; |
| @@ -379,12 +396,13 @@ Path AppliedDecorationPainter::PrepareWavyStrokePath() { |
| // The minimum height of the curve is also approximately 3 pixels. Increases |
| // the curve's height |
| // as strockThickness increases to make the curve looks better. |
| - float control_point_distance = 3 * std::max<float>(2, thickness_); |
| + float control_point_distance = |
| + 3 * std::max<float>(2, decoration_info_.thickness); |
| // Increment used to form the diamond shape between start point (p1), control |
| // points and end point (p2) along the axis of the decoration. Makes the |
| // curve wider as strockThickness increases to make the curve looks better. |
| - float step = 2 * std::max<float>(2, thickness_); |
| + float step = 2 * std::max<float>(2, decoration_info_.thickness); |
| bool is_vertical_line = (p1.X() == p2.X()); |
| @@ -467,6 +485,177 @@ static bool PaintsCompositionMarkers(const LayoutObject& layout_object) { |
| .size() > 0; |
| } |
| +static void PrepareContextForDecoration(GraphicsContext& context, |
| + GraphicsContextStateSaver& state_saver, |
| + bool is_horizontal, |
| + const TextPainter::Style& text_style, |
| + const LayoutTextCombine* combined_text, |
| + const LayoutRect& box_rect) { |
| + TextPainter::UpdateGraphicsContext(context, text_style, is_horizontal, |
| + state_saver); |
| + if (combined_text) |
| + context.ConcatCTM(TextPainter::Rotation(box_rect, TextPainter::kClockwise)); |
| +} |
| + |
| +static void RestoreContextFromDecoration(GraphicsContext& context, |
| + const LayoutTextCombine* combined_text, |
| + const LayoutRect& box_rect) { |
| + if (combined_text) { |
| + context.ConcatCTM( |
| + TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); |
| + } |
| +} |
| + |
| +static void ComputeDecorationInfo( |
| + DecorationInfo& decoration_info, |
| + const InlineTextBox& box, |
| + const LayoutPoint& box_origin, |
| + const Vector<AppliedTextDecoration>& decorations) { |
| + LayoutPoint local_origin = LayoutPoint(box_origin); |
| + LayoutUnit width = box.LogicalWidth(); |
| + if (box.Truncation() != kCNoTruncation) { |
| + bool ltr = box.IsLeftToRightDirection(); |
| + bool flow_is_ltr = |
| + box.GetLineLayoutItem().Style()->IsLeftToRightDirection(); |
| + width = LayoutUnit(box.GetLineLayoutItem().Width( |
| + ltr == flow_is_ltr ? box.Start() : box.Start() + box.Truncation(), |
| + ltr == flow_is_ltr ? box.Truncation() : box.Len() - box.Truncation(), |
| + box.TextPos(), flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, |
| + box.IsFirstLineStyle())); |
| + if (!flow_is_ltr) { |
| + local_origin.Move(box.LogicalWidth() - width, LayoutUnit()); |
| + } |
| + } |
| + decoration_info.width = width; |
| + decoration_info.local_origin = FloatPoint(local_origin); |
| + |
| + decoration_info.antialias = ShouldSetDecorationAntialias(decorations); |
| + |
| + decoration_info.style = |
| + LineLayoutAPIShim::LayoutObjectFrom(box.GetLineLayoutItem()) |
| + ->Style(box.IsFirstLineStyle()); |
| + decoration_info.font_data = decoration_info.style->GetFont().PrimaryFont(); |
| + DCHECK(decoration_info.font_data); |
| + decoration_info.baseline = |
| + decoration_info.font_data |
| + ? 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); |
| + } |
| + 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; |
| +} |
| + |
| +static void PaintDecorationsExceptLineThrough( |
| + TextPainter& text_painter, |
| + bool& has_line_through_decoration, |
| + const InlineTextBox& box, |
| + const DecorationInfo& decoration_info, |
| + const PaintInfo& paint_info, |
| + const Vector<AppliedTextDecoration>& decorations) { |
| + GraphicsContext& context = paint_info.context; |
| + GraphicsContextStateSaver state_saver(context); |
| + context.SetStrokeThickness(decoration_info.thickness); |
| + bool skip_intercepts = |
| + decoration_info.style->GetTextDecorationSkip() & kTextDecorationSkipInk; |
| + |
| + // text-underline-position may flip underline and overline. |
| + ResolvedUnderlinePosition underline_position = |
| + ResolveUnderlinePosition(*decoration_info.style, &box); |
| + bool flip_underline_and_overline = false; |
| + if (underline_position == ResolvedUnderlinePosition::kOver) { |
| + flip_underline_and_overline = true; |
| + underline_position = ResolvedUnderlinePosition::kUnder; |
| + } |
| + |
| + for (const AppliedTextDecoration& decoration : decorations) { |
| + TextDecoration lines = decoration.Lines(); |
| + if (flip_underline_and_overline) { |
| + lines = static_cast<TextDecoration>( |
| + 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); |
| + AppliedDecorationPainter decoration_painter( |
| + context, decoration_info, underline_offset, decoration, |
| + decoration_info.double_offset, 1); |
| + if (skip_intercepts) { |
| + text_painter.ClipDecorationsStripe( |
| + -decoration_info.baseline + |
| + decoration_painter.DecorationBounds().Y() - |
| + decoration_info.local_origin.Y(), |
| + decoration_painter.DecorationBounds().Height(), |
| + decoration_info.thickness); |
| + } |
| + decoration_painter.Paint(); |
| + } |
| + if (lines & kTextDecorationOverline) { |
| + const int overline_offset = |
| + ComputeOverlineOffset(*decoration_info.style, &box); |
| + AppliedDecorationPainter decoration_painter( |
| + context, decoration_info, overline_offset, decoration, |
| + -decoration_info.double_offset, 1); |
| + if (skip_intercepts) { |
| + text_painter.ClipDecorationsStripe( |
| + -decoration_info.baseline + |
| + decoration_painter.DecorationBounds().Y() - |
| + decoration_info.local_origin.Y(), |
| + decoration_painter.DecorationBounds().Height(), |
| + decoration_info.thickness); |
| + } |
| + decoration_painter.Paint(); |
| + } |
| + // We could instead build a vector of the TextDecoration instances needing |
| + // line-through but this is a rare case so better to avoid vector overhead. |
| + has_line_through_decoration |= (lines & kTextDecorationLineThrough); |
| + } |
| +} |
| + |
| +static void PaintDecorationsOnlyLineThrough( |
| + TextPainter& text_painter, |
| + const DecorationInfo& decoration_info, |
| + const PaintInfo& paint_info, |
| + const Vector<AppliedTextDecoration>& decorations) { |
| + GraphicsContext& context = paint_info.context; |
| + GraphicsContextStateSaver state_saver(context); |
| + context.SetStrokeThickness(decoration_info.thickness); |
| + for (const AppliedTextDecoration& decoration : decorations) { |
| + TextDecoration lines = decoration.Lines(); |
| + if (lines & kTextDecorationLineThrough) { |
| + const float line_through_offset = 2 * decoration_info.baseline / 3; |
| + AppliedDecorationPainter decoration_painter( |
| + context, decoration_info, line_through_offset, decoration, |
| + decoration_info.double_offset, 0); |
| + // No skip: ink for line-through, |
| + // compare https://github.com/w3c/csswg-drafts/issues/711 |
| + decoration_painter.Paint(); |
| + } |
| + } |
| +} |
| + |
| void InlineTextBoxPainter::Paint(const PaintInfo& paint_info, |
| const LayoutPoint& paint_offset) { |
| if (!ShouldPaintTextBox(paint_info)) |
| @@ -668,6 +857,23 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info, |
| text_painter.SetEllipsisOffset(inline_text_box_.Truncation()); |
| if (!paint_selected_text_only) { |
| + // Paint text decorations except line-through. |
| + DecorationInfo decoration_info; |
| + bool has_line_through_decoration = false; |
| + if (style_to_use.TextDecorationsInEffect() != kTextDecorationNone && |
| + inline_text_box_.Truncation() != kCFullTruncation) { |
| + ComputeDecorationInfo(decoration_info, inline_text_box_, box_origin, |
| + style_to_use.AppliedTextDecorations()); |
| + GraphicsContextStateSaver state_saver(context, false); |
| + PrepareContextForDecoration(context, state_saver, |
| + inline_text_box_.IsHorizontal(), text_style, |
| + combined_text, box_rect); |
| + PaintDecorationsExceptLineThrough( |
| + text_painter, has_line_through_decoration, inline_text_box_, |
| + decoration_info, paint_info, style_to_use.AppliedTextDecorations()); |
| + RestoreContextFromDecoration(context, combined_text, box_rect); |
| + } |
| + |
| int start_offset = 0; |
| int end_offset = length; |
| // Where the text and its flow have opposite directions then our offset into |
| @@ -684,6 +890,17 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info, |
| } |
| text_painter.Paint(start_offset, end_offset, length, text_style); |
| + |
| + // Paint line-through decoration if needed. |
| + if (has_line_through_decoration) { |
| + GraphicsContextStateSaver state_saver(context, false); |
| + PrepareContextForDecoration(context, state_saver, |
| + inline_text_box_.IsHorizontal(), text_style, |
| + combined_text, box_rect); |
| + PaintDecorationsOnlyLineThrough(text_painter, decoration_info, paint_info, |
| + style_to_use.AppliedTextDecorations()); |
| + RestoreContextFromDecoration(context, combined_text, box_rect); |
| + } |
| } |
| if ((paint_selected_text_only || paint_selected_text_separately) && |
| @@ -692,24 +909,6 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info, |
| text_painter.Paint(selection_start, selection_end, length, selection_style); |
| } |
| - // Paint decorations |
| - if (style_to_use.TextDecorationsInEffect() != kTextDecorationNone && |
| - !paint_selected_text_only) { |
| - GraphicsContextStateSaver state_saver(context, false); |
| - |
| - TextPainter::UpdateGraphicsContext( |
| - context, text_style, inline_text_box_.IsHorizontal(), state_saver); |
| - |
| - if (combined_text) |
| - context.ConcatCTM( |
| - TextPainter::Rotation(box_rect, TextPainter::kClockwise)); |
| - PaintDecorations(text_painter, paint_info, box_origin, |
| - style_to_use.AppliedTextDecorations()); |
| - if (combined_text) |
| - context.ConcatCTM( |
| - TextPainter::Rotation(box_rect, TextPainter::kCounterclockwise)); |
| - } |
| - |
| if (paint_info.phase == kPaintPhaseForeground) |
| PaintDocumentMarkers(paint_info, box_origin, style_to_use, font, |
| DocumentMarkerPaintPhase::kForeground); |
| @@ -1106,135 +1305,6 @@ void InlineTextBoxPainter::ExpandToIncludeNewlineForSelection( |
| rect.Expand(outsets); |
| } |
| -void InlineTextBoxPainter::PaintDecorations( |
| - TextPainter& text_painter, |
| - const PaintInfo& paint_info, |
| - const LayoutPoint& box_origin, |
| - const Vector<AppliedTextDecoration>& decorations) { |
| - if (inline_text_box_.Truncation() == kCFullTruncation) |
| - return; |
| - |
| - GraphicsContext& context = paint_info.context; |
| - GraphicsContextStateSaver state_saver(context); |
| - |
| - LayoutPoint local_origin(box_origin); |
| - |
| - LayoutUnit width = inline_text_box_.LogicalWidth(); |
| - if (inline_text_box_.Truncation() != kCNoTruncation) { |
| - bool ltr = inline_text_box_.IsLeftToRightDirection(); |
| - bool flow_is_ltr = |
| - inline_text_box_.GetLineLayoutItem().Style()->IsLeftToRightDirection(); |
| - width = LayoutUnit(inline_text_box_.GetLineLayoutItem().Width( |
| - ltr == flow_is_ltr |
| - ? inline_text_box_.Start() |
| - : inline_text_box_.Start() + inline_text_box_.Truncation(), |
| - ltr == flow_is_ltr |
| - ? inline_text_box_.Truncation() |
| - : inline_text_box_.Len() - inline_text_box_.Truncation(), |
| - inline_text_box_.TextPos(), |
| - flow_is_ltr ? TextDirection::kLtr : TextDirection::kRtl, |
| - inline_text_box_.IsFirstLineStyle())); |
| - if (!flow_is_ltr) |
| - local_origin.Move(inline_text_box_.LogicalWidth() - width, LayoutUnit()); |
| - } |
| - |
| - LayoutObject& text_box_layout_object = InlineLayoutObject(); |
| - |
| - const ComputedStyle& style_to_use = |
| - text_box_layout_object.StyleRef(inline_text_box_.IsFirstLineStyle()); |
| - const SimpleFontData* font_data = style_to_use.GetFont().PrimaryFont(); |
| - DCHECK(font_data); |
| - float baseline = font_data ? 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 (font_data) { |
| - text_decoration_thickness = |
| - font_data->GetFontMetrics().UnderlineThickness(); |
| - font_height_int = (int)(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, style_to_use.ComputedFontSize() / 10.f); |
| - |
| - context.SetStrokeThickness(text_decoration_thickness); |
| - |
| - bool antialias_decoration = ShouldSetDecorationAntialias(decorations); |
| - |
| - // Offset between lines - always non-zero, so lines never cross each other. |
| - float double_offset = text_decoration_thickness + 1.f; |
| - bool skip_intercepts = |
| - style_to_use.GetTextDecorationSkip() & kTextDecorationSkipInk; |
| - |
| - // text-underline-position may flip underline and overline. |
| - ResolvedUnderlinePosition underline_position = |
| - ResolveUnderlinePosition(style_to_use, &inline_text_box_); |
| - bool flip_underline_and_overline = false; |
| - if (underline_position == ResolvedUnderlinePosition::kOver) { |
| - flip_underline_and_overline = true; |
| - underline_position = ResolvedUnderlinePosition::kUnder; |
| - } |
| - |
| - for (const AppliedTextDecoration& decoration : decorations) { |
| - TextDecoration lines = decoration.Lines(); |
| - if (flip_underline_and_overline) { |
| - lines = static_cast<TextDecoration>( |
| - lines ^ (kTextDecorationUnderline | kTextDecorationOverline)); |
| - } |
| - if ((lines & kTextDecorationUnderline) && font_data) { |
| - const int underline_offset = ComputeUnderlineOffset( |
| - underline_position, style_to_use, font_data->GetFontMetrics(), |
| - &inline_text_box_, text_decoration_thickness); |
| - AppliedDecorationPainter decoration_painter( |
| - context, FloatPoint(local_origin) + FloatPoint(0, underline_offset), |
| - width.ToFloat(), decoration, text_decoration_thickness, double_offset, |
| - 1, antialias_decoration); |
| - if (skip_intercepts) { |
| - text_painter.ClipDecorationsStripe( |
| - -baseline + decoration_painter.DecorationBounds().Y() - |
| - FloatPoint(local_origin).Y(), |
| - decoration_painter.DecorationBounds().Height(), |
| - text_decoration_thickness); |
| - } |
| - decoration_painter.Paint(); |
| - } |
| - if (lines & kTextDecorationOverline) { |
| - const int overline_offset = |
| - ComputeOverlineOffset(style_to_use, &inline_text_box_); |
| - AppliedDecorationPainter decoration_painter( |
| - context, FloatPoint(local_origin) + FloatPoint(0, overline_offset), |
| - width.ToFloat(), decoration, text_decoration_thickness, |
| - -double_offset, 1, antialias_decoration); |
| - if (skip_intercepts) { |
| - text_painter.ClipDecorationsStripe( |
| - -baseline + decoration_painter.DecorationBounds().Y() - |
| - FloatPoint(local_origin).Y(), |
| - decoration_painter.DecorationBounds().Height(), |
| - text_decoration_thickness); |
| - } |
| - decoration_painter.Paint(); |
| - } |
| - if (lines & kTextDecorationLineThrough) { |
| - const float line_through_offset = 2 * baseline / 3; |
| - AppliedDecorationPainter decoration_painter( |
| - context, |
| - FloatPoint(local_origin) + FloatPoint(0, line_through_offset), |
| - width.ToFloat(), decoration, text_decoration_thickness, double_offset, |
| - 0, antialias_decoration); |
| - // No skip: ink for line-through, |
| - // compare https://github.com/w3c/csswg-drafts/issues/711 |
| - decoration_painter.Paint(); |
| - } |
| - } |
| -} |
| - |
| void InlineTextBoxPainter::PaintCompositionUnderline( |
| GraphicsContext& context, |
| const LayoutPoint& box_origin, |