Index: ui/gfx/render_text_unittest.cc |
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc |
index dfd2111875670aa5eab66ab8ce8a42a10630db6c..d262f5f5d790806a4c9ef9fd07d905702f08f243 100644 |
--- a/ui/gfx/render_text_unittest.cc |
+++ b/ui/gfx/render_text_unittest.cc |
@@ -116,6 +116,10 @@ class RenderTextTestApi { |
return render_text_->GetAlignmentOffset(line_number); |
} |
+ int GetDisplayTextBaseline() { |
+ return render_text_->GetDisplayTextBaseline(); |
+ } |
+ |
private: |
RenderText* render_text_; |
@@ -4405,6 +4409,100 @@ TEST_P(RenderTextTest, InvalidFont) { |
DrawVisualText(); |
} |
+// Ensures that text is centered vertically and consistently when either the |
+// display rectangle height changes, or when the minimum line height changes. |
+// The difference between the two is the selection rectangle, which should match |
+// the line height. |
+TEST_P(RenderTextHarfBuzzTest, BaselineWithLineHeight) { |
+ RenderText* render_text = GetRenderText(); |
+ const int font_height = render_text->font_list().GetHeight(); |
+ render_text->SetDisplayRect(Rect(500, font_height)); |
+ render_text->SetText(ASCIIToUTF16("abc")); |
+ |
+ // Select everything so the test can use GetSelectionBoundsUnion(). |
+ render_text->SelectAll(false); |
+ |
+ const int normal_baseline = test_api()->GetDisplayTextBaseline(); |
+ ASSERT_EQ(1u, test_api()->lines().size()); |
+ EXPECT_EQ(font_height, test_api()->lines()[0].size.height()); |
+ |
+ // With a matching display height, the baseline calculated using font metrics |
+ // and the baseline from the layout engine should agree. This works because |
+ // the text string is simple (exotic glyphs may use fonts with different |
+ // metrics). |
+ EXPECT_EQ(normal_baseline, render_text->GetBaseline()); |
+ EXPECT_EQ(0, render_text->GetLineOffset(0).y()); |
+ |
+ const gfx::Rect normal_selection_bounds = GetSelectionBoundsUnion(); |
+ |
+ // Sanity check: selection should start from (0,0). |
+ EXPECT_EQ(gfx::Vector2d(), normal_selection_bounds.OffsetFromOrigin()); |
+ |
+ constexpr int kDelta = 16; |
+ |
+ // Grow just the display rectangle. |
+ render_text->SetDisplayRect(Rect(500, font_height + kDelta)); |
+ |
+ // The display text baseline does not move: GetLineOffset() moves it instead. |
+ EXPECT_EQ(normal_baseline, test_api()->GetDisplayTextBaseline()); |
+ |
+ ASSERT_EQ(1u, test_api()->lines().size()); |
+ EXPECT_EQ(font_height, test_api()->lines()[0].size.height()); |
+ |
+ // Save the baseline calculated using the display rectangle before enabling |
+ // multi-line or SetMinLineHeight(). |
+ const int reported_baseline = render_text->GetBaseline(); |
+ const int baseline_shift = reported_baseline - normal_baseline; |
+ |
+ // When line height matches font height, this should match the line offset. |
+ EXPECT_EQ(baseline_shift, render_text->GetLineOffset(0).y()); |
+ |
+ // The actual shift depends on font metrics, and the calculations done in |
+ // RenderText::DetermineBaselineCenteringText(). Do a sanity check that the |
+ // "centering" part is happening within some tolerance by ensuring the shift |
+ // is within a pixel of (kDelta / 2). That is, 7, 8 or 9 pixels (for a delta |
+ // of 16). An unusual font in future may need more leeway. |
+ constexpr int kFuzz = 1; // If the next EXPECT fails, try increasing this. |
+ EXPECT_LE(abs(baseline_shift - kDelta / 2), kFuzz); |
+ |
+ // Increasing display height (but not line height) should shift the selection |
+ // bounds down by |baseline_shift|, but leave a matching size. |
+ gfx::Rect current_selection_bounds = GetSelectionBoundsUnion(); |
+ EXPECT_EQ(baseline_shift, current_selection_bounds.y()); |
+ EXPECT_EQ(0, current_selection_bounds.x()); |
+ EXPECT_EQ(normal_selection_bounds.size(), current_selection_bounds.size()); |
+ |
+ // Now increase the line height, but remain single-line. Note the line height |
+ // now matches the display rect. |
+ render_text->SetMinLineHeight(font_height + kDelta); |
+ int display_text_baseline = test_api()->GetDisplayTextBaseline(); |
+ ASSERT_EQ(1u, test_api()->lines().size()); |
+ EXPECT_EQ(font_height + kDelta, test_api()->lines()[0].size.height()); |
+ |
+ // The line offset should go back to zero, but now the display text baseline |
+ // should shift down to compensate, and the shift amount should match. |
+ EXPECT_EQ(0, render_text->GetLineOffset(0).y()); |
+ EXPECT_EQ(normal_baseline + baseline_shift, display_text_baseline); |
+ |
+ // Now selection bounds should grow in height, but not shift its origin. |
+ current_selection_bounds = GetSelectionBoundsUnion(); |
+ EXPECT_EQ(font_height + kDelta, current_selection_bounds.height()); |
+ EXPECT_EQ(normal_selection_bounds.width(), current_selection_bounds.width()); |
+ EXPECT_EQ(gfx::Vector2d(), current_selection_bounds.OffsetFromOrigin()); |
+ |
+ // Flipping the multiline flag should change nothing. |
+ render_text->SetMultiline(true); |
+ display_text_baseline = test_api()->GetDisplayTextBaseline(); |
+ ASSERT_EQ(1u, test_api()->lines().size()); |
+ EXPECT_EQ(font_height + kDelta, test_api()->lines()[0].size.height()); |
+ EXPECT_EQ(0, render_text->GetLineOffset(0).y()); |
+ EXPECT_EQ(normal_baseline + baseline_shift, display_text_baseline); |
+ current_selection_bounds = GetSelectionBoundsUnion(); |
+ EXPECT_EQ(font_height + kDelta, current_selection_bounds.height()); |
+ EXPECT_EQ(normal_selection_bounds.width(), current_selection_bounds.width()); |
+ EXPECT_EQ(gfx::Vector2d(), current_selection_bounds.OffsetFromOrigin()); |
+} |
+ |
// Prefix for test instantiations intentionally left blank since each test |
// fixture class has a single parameterization. |
#if defined(OS_MACOSX) |