Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Unified Diff: third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp

Issue 2643413002: Fix 'text-underline-position: under' to use em height ascent/descent (Closed)
Patch Set: Rebaseline Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698