Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

fix underline lineThrough and overline display exception, in the case… #16709

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 69 additions & 24 deletions third_party/txt/src/txt/paragraph_txt.cc
Original file line number Diff line number Diff line change
@@ -1175,6 +1175,7 @@ void ParagraphTxt::Layout(double width) {
});

longest_line_ = max_right_ - min_left_;
AdjustDecorationValues();
}

void ParagraphTxt::UpdateLineMetrics(const SkFontMetrics& metrics,
@@ -1430,16 +1431,7 @@ void ParagraphTxt::PaintDecorations(SkCanvas* canvas,

double width = record.GetRunWidth();

SkScalar underline_thickness;
if ((metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kUnderlineThicknessIsValid_Flag) &&
metrics.fUnderlineThickness > 0) {
underline_thickness = metrics.fUnderlineThickness;
} else {
// Backup value if the fUnderlineThickness metric is not available:
// Divide by 14pt as it is the default size.
underline_thickness = record.style().font_size / 14.0f;
}
SkScalar underline_thickness = underline_thickness_;
paint.setStrokeWidth(underline_thickness *
record.style().decoration_thickness_multiplier);

@@ -1499,11 +1491,7 @@ void ParagraphTxt::PaintDecorations(SkCanvas* canvas,
double y_offset_original = y_offset;
// Underline
if (record.style().decoration & TextDecoration::kUnderline) {
y_offset +=
(metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kUnderlinePositionIsValid_Flag)
? metrics.fUnderlinePosition
: underline_thickness;
y_offset += underline_y_offset_;
if (record.style().decoration_style != TextDecorationStyle::kWavy) {
canvas->drawLine(x, y + y_offset, x + width, y + y_offset, paint);
} else {
@@ -1517,7 +1505,7 @@ void ParagraphTxt::PaintDecorations(SkCanvas* canvas,
if (record.style().decoration & TextDecoration::kOverline) {
// We subtract fAscent here because for double overlines, we want the
// second line to be above, not below the first.
y_offset -= metrics.fAscent;
y_offset += overline_y_offset_;
if (record.style().decoration_style != TextDecorationStyle::kWavy) {
canvas->drawLine(x, y - y_offset, x + width, y - y_offset, paint);
} else {
@@ -1531,18 +1519,12 @@ void ParagraphTxt::PaintDecorations(SkCanvas* canvas,
if (record.style().decoration & TextDecoration::kLineThrough) {
if (metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kStrikeoutThicknessIsValid_Flag)
paint.setStrokeWidth(metrics.fStrikeoutThickness *
paint.setStrokeWidth(strikeout_thickness_ *
record.style().decoration_thickness_multiplier);
// Make sure the double line is "centered" vertically.
y_offset += (decoration_count - 1.0) * underline_thickness *
kDoubleDecorationSpacing / -2.0;
y_offset +=
(metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kStrikeoutThicknessIsValid_Flag)
? metrics.fStrikeoutPosition
// Backup value if the strikeoutposition metric is not
// available:
: metrics.fXHeight / -2.0;
y_offset += line_through_y_offset_;
if (record.style().decoration_style != TextDecorationStyle::kWavy) {
canvas->drawLine(x, y + y_offset, x + width, y + y_offset, paint);
} else {
@@ -1555,6 +1537,69 @@ void ParagraphTxt::PaintDecorations(SkCanvas* canvas,
}
}

void ParagraphTxt::AdjustDecorationValues() {
underline_y_offset_ = 0;
overline_y_offset_ = 0;
line_through_y_offset_ = 0;
strikeout_thickness_ = 0;
underline_thickness_ = 0;
for (const PaintRecord& record : records_) {
const SkFontMetrics& metrics = record.metrics();
SkScalar underline_thickness;
if ((metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kUnderlineThicknessIsValid_Flag) &&
metrics.fUnderlineThickness > 0) {
underline_thickness = metrics.fUnderlineThickness;
} else {
// Backup value if the fUnderlineThickness metric is not available:
// Divide by 14pt as it is the default size.
underline_thickness = record.style().font_size / 14.0f;
}
// Get the max value
underline_thickness_ = underline_thickness_ < underline_thickness
? underline_thickness
: underline_thickness_;

// Underline
if (record.style().decoration & TextDecoration::kUnderline) {
SkScalar underline_y_offset =
(metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kUnderlinePositionIsValid_Flag)
? metrics.fUnderlinePosition
: underline_thickness;
underline_y_offset_ = underline_y_offset_ < underline_y_offset
? underline_y_offset
: underline_y_offset_;
}
// Overline
if (record.style().decoration & TextDecoration::kOverline) {
SkScalar overline_y_offset = -metrics.fAscent;
overline_y_offset_ = overline_y_offset_ < overline_y_offset
? overline_y_offset
: overline_y_offset_;
}

// Strikethrough
if (record.style().decoration & TextDecoration::kLineThrough) {
if (metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kStrikeoutThicknessIsValid_Flag)
strikeout_thickness_ =
strikeout_thickness_ < metrics.fStrikeoutThickness
? metrics.fStrikeoutThickness
: strikeout_thickness_;

SkScalar line_through_y_offset =
(metrics.fFlags &
SkFontMetrics::FontMetricsFlags::kStrikeoutThicknessIsValid_Flag)
? metrics.fStrikeoutPosition
: metrics.fXHeight / -2.0;
line_through_y_offset_ = line_through_y_offset_ > line_through_y_offset
? line_through_y_offset
: line_through_y_offset_;
}
}
}

void ParagraphTxt::ComputeWavyDecoration(SkPath& path,
double x,
double y,
11 changes: 11 additions & 0 deletions third_party/txt/src/txt/paragraph_txt.h
Original file line number Diff line number Diff line change
@@ -192,6 +192,14 @@ class ParagraphTxt : public Paragraph {
// Stores the result of Layout().
std::vector<PaintRecord> records_;

// Values for adjust the underline lineThrough and overline, in the case of
// multiple fonts.
SkScalar underline_y_offset_;
SkScalar line_through_y_offset_;
SkScalar overline_y_offset_;
SkScalar underline_thickness_;
SkScalar strikeout_thickness_;

bool did_exceed_max_lines_;

// Strut metrics of zero will have no effect on the layout.
@@ -383,6 +391,9 @@ class ParagraphTxt : public Paragraph {
void PaintDecorations(SkCanvas* canvas,
const PaintRecord& record,
SkPoint base_offset);
// adjust values for the underline lineThrough and overline, in the case of
// multiple fonts.
void AdjustDecorationValues();

// Computes the beziers for a wavy decoration. The results will be
// applied to path.