| 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..80a7b90c9b77fd15493499141bc206560a440f0a 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,
|
| 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) != 0);
|
| + }
|
| +}
|
| +
|
| +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,
|
|
|