| Index: ui/gfx/render_text_unittest.cc
|
| diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
|
| index e274a266eaa9acfd18bfbaca370a327215f5f7f8..432d4ab1c2b4662cb7aab3caccf6d36842d3a85d 100644
|
| --- a/ui/gfx/render_text_unittest.cc
|
| +++ b/ui/gfx/render_text_unittest.cc
|
| @@ -163,6 +163,48 @@ class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
|
| DISALLOW_COPY_AND_ASSIGN(TestSkiaTextRenderer);
|
| };
|
|
|
| +// Given a buffer to test against, this can be used to test various areas of the
|
| +// rectangular buffer against a specific color value.
|
| +class TestRectangleBuffer {
|
| + public:
|
| + TestRectangleBuffer(const wchar_t* string,
|
| + const SkColor* buffer,
|
| + uint32_t stride,
|
| + uint32_t row_count)
|
| + : string_(string),
|
| + buffer_(buffer),
|
| + stride_(stride),
|
| + row_count_(row_count) {}
|
| +
|
| + // Test if any values in the rectangular area are anything other than |color|.
|
| + void EnsureSolidRect(SkColor color,
|
| + int left,
|
| + int top,
|
| + int width,
|
| + int height) const {
|
| + ASSERT_LT(top, row_count_) << string_;
|
| + ASSERT_LE(top + height, row_count_) << string_;
|
| + ASSERT_LT(left, stride_) << string_;
|
| + ASSERT_LE(left + width, stride_) << string_ << ", left " << left
|
| + << ", width " << width << ", stride_ "
|
| + << stride_;
|
| + for (int y = top; y < top + height; ++y) {
|
| + for (int x = left; x < left + width; ++x) {
|
| + SkColor color = buffer_[x + y * stride_];
|
| + EXPECT_EQ(SK_ColorWHITE, color) << string_ << " at " << x << ", " << y;
|
| + }
|
| + }
|
| + }
|
| +
|
| + private:
|
| + const wchar_t* string_;
|
| + const SkColor* buffer_;
|
| + int stride_;
|
| + int row_count_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestRectangleBuffer);
|
| +};
|
| +
|
| } // namespace
|
|
|
| class RenderTextTest : public testing::Test {
|
| @@ -175,6 +217,8 @@ TEST_F(RenderTextTest, DefaultStyle) {
|
| const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
|
| for (size_t i = 0; i < arraysize(cases); ++i) {
|
| EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLACK));
|
| + EXPECT_TRUE(
|
| + render_text->baselines().EqualsValueForTesting(NORMAL_BASELINE));
|
| for (size_t style = 0; style < NUM_TEXT_STYLES; ++style)
|
| EXPECT_TRUE(render_text->styles()[style].EqualsValueForTesting(false));
|
| render_text->SetText(WideToUTF16(cases[i]));
|
| @@ -186,11 +230,13 @@ TEST_F(RenderTextTest, SetColorAndStyle) {
|
| scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
|
| const SkColor color = SK_ColorRED;
|
| render_text->SetColor(color);
|
| + render_text->SetBaselineStyle(SUPERSCRIPT);
|
| render_text->SetStyle(BOLD, true);
|
| render_text->SetStyle(UNDERLINE, false);
|
| const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
|
| for (size_t i = 0; i < arraysize(cases); ++i) {
|
| EXPECT_TRUE(render_text->colors().EqualsValueForTesting(color));
|
| + EXPECT_TRUE(render_text->baselines().EqualsValueForTesting(SUPERSCRIPT));
|
| EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(true));
|
| EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsValueForTesting(false));
|
| render_text->SetText(WideToUTF16(cases[i]));
|
| @@ -209,32 +255,51 @@ TEST_F(RenderTextTest, ApplyColorAndStyle) {
|
|
|
| // Apply a ranged color and style and check the resulting breaks.
|
| render_text->ApplyColor(SK_ColorRED, Range(1, 4));
|
| + render_text->ApplyBaselineStyle(SUPERIOR, Range(2, 4));
|
| render_text->ApplyStyle(BOLD, true, Range(2, 5));
|
| std::vector<std::pair<size_t, SkColor> > expected_color;
|
| expected_color.push_back(std::pair<size_t, SkColor>(0, SK_ColorBLACK));
|
| expected_color.push_back(std::pair<size_t, SkColor>(1, SK_ColorRED));
|
| expected_color.push_back(std::pair<size_t, SkColor>(4, SK_ColorBLACK));
|
| EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color));
|
| + std::vector<std::pair<size_t, BaselineStyle>> expected_baseline_style;
|
| + expected_baseline_style.push_back(
|
| + std::pair<size_t, BaselineStyle>(0, NORMAL_BASELINE));
|
| + expected_baseline_style.push_back(
|
| + std::pair<size_t, BaselineStyle>(2, SUPERIOR));
|
| + expected_baseline_style.push_back(
|
| + std::pair<size_t, BaselineStyle>(4, NORMAL_BASELINE));
|
| + EXPECT_TRUE(
|
| + render_text->baselines().EqualsForTesting(expected_baseline_style));
|
| std::vector<std::pair<size_t, bool> > expected_style;
|
| expected_style.push_back(std::pair<size_t, bool>(0, false));
|
| expected_style.push_back(std::pair<size_t, bool>(2, true));
|
| expected_style.push_back(std::pair<size_t, bool>(5, false));
|
| EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style));
|
|
|
| - // Ensure setting a color and style overrides the ranged colors and styles.
|
| + // Ensure setting a color, baseline, and style overrides the ranged colors,
|
| + // baseline, and styles.
|
| render_text->SetColor(SK_ColorBLUE);
|
| EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLUE));
|
| + render_text->SetBaselineStyle(SUBSCRIPT);
|
| + EXPECT_TRUE(render_text->baselines().EqualsValueForTesting(SUBSCRIPT));
|
| render_text->SetStyle(BOLD, false);
|
| EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(false));
|
|
|
| - // Apply a color and style over the text end and check the resulting breaks.
|
| - // (INT_MAX should be used instead of the text length for the range end)
|
| + // Apply a color, baseline, and style over the text end and check the
|
| + // resulting breaks (INT_MAX should be used instead of the text length for
|
| + // the range end)
|
| const size_t text_length = render_text->text().length();
|
| render_text->ApplyColor(SK_ColorRED, Range(0, text_length));
|
| + render_text->ApplyBaselineStyle(SUPERIOR, Range(0, text_length));
|
| render_text->ApplyStyle(BOLD, true, Range(2, text_length));
|
| std::vector<std::pair<size_t, SkColor> > expected_color_end;
|
| expected_color_end.push_back(std::pair<size_t, SkColor>(0, SK_ColorRED));
|
| EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color_end));
|
| + std::vector<std::pair<size_t, BaselineStyle>> expected_baseline_end;
|
| + expected_baseline_end.push_back(
|
| + std::pair<size_t, BaselineStyle>(0, SUPERIOR));
|
| + EXPECT_TRUE(render_text->baselines().EqualsForTesting(expected_baseline_end));
|
| std::vector<std::pair<size_t, bool> > expected_style_end;
|
| expected_style_end.push_back(std::pair<size_t, bool>(0, false));
|
| expected_style_end.push_back(std::pair<size_t, bool>(2, true));
|
| @@ -2588,40 +2653,152 @@ TEST_F(RenderTextTest, HarfBuzz_UnicodeFallback) {
|
| #endif // defined(OS_WIN) || defined(OS_MACOSX)
|
|
|
| // Ensure that the width reported by RenderText is sufficient for drawing. Draws
|
| -// to a canvas and checks whether any pixel beyond the width is colored.
|
| +// to a canvas and checks whether any pixel beyond the bounding rectangle is
|
| +// colored.
|
| TEST_F(RenderTextTest, TextDoesntClip) {
|
| - const wchar_t* kTestStrings[] = { L"Save", L"Remove", L"TEST", L"W", L"WWW" };
|
| + const wchar_t* kTestStrings[] = {
|
| + L" ",
|
| + // TODO(dschuyler): Underscores draw outside GetStringSize;
|
| + // crbug.com/459812. This appears to be a preexisting issue that wasn't
|
| + // revealed by the prior unit tests.
|
| + // L"TEST_______",
|
| + L"TEST some stuff",
|
| + L"WWWWWWWWWW",
|
| + L"gAXAXAXAXAXAXA",
|
| + // TODO(dschuyler): A-Ring draws outside GetStringSize; crbug.com/459812.
|
| + // L"g\x00C5X\x00C5X\x00C5X\x00C5X\x00C5X\x00C5X\x00C5",
|
| + L"\x0647\x0654\x0647\x0654\x0647\x0654\x0647\x0654\x0645\x0631\x062D"
|
| + L"\x0628\x0627"};
|
| const Size kCanvasSize(300, 50);
|
| - const int kTestWidth = 10;
|
| + const int kTestSize = 10;
|
|
|
| skia::RefPtr<SkSurface> surface = skia::AdoptRef(
|
| SkSurface::NewRasterN32Premul(kCanvasSize.width(), kCanvasSize.height()));
|
| scoped_ptr<Canvas> canvas(
|
| Canvas::CreateCanvasWithoutScaling(surface->getCanvas(), 1.0f));
|
| scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
|
| - render_text->SetDisplayRect(Rect(kCanvasSize));
|
| - render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + render_text->SetHorizontalAlignment(ALIGN_LEFT);
|
| render_text->SetColor(SK_ColorBLACK);
|
|
|
| for (auto string : kTestStrings) {
|
| surface->getCanvas()->clear(SK_ColorWHITE);
|
| render_text->SetText(WideToUTF16(string));
|
| + const Size string_size = render_text->GetStringSize();
|
| + render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2));
|
| + render_text->ApplyBaselineStyle(SUPERIOR, Range(3, 4));
|
| + render_text->ApplyBaselineStyle(INFERIOR, Range(5, 6));
|
| + render_text->ApplyBaselineStyle(SUBSCRIPT, Range(7, 8));
|
| render_text->SetStyle(BOLD, true);
|
| + render_text->SetDisplayRect(
|
| + Rect(kTestSize, kTestSize, string_size.width(), string_size.height()));
|
| + // Allow the RenderText to paint outside of its display rect.
|
| + render_text->set_clip_to_display_rect(false);
|
| + ASSERT_LE(string_size.width() + kTestSize * 2, kCanvasSize.width());
|
| +
|
| render_text->Draw(canvas.get());
|
| - int width = render_text->GetStringSize().width();
|
| - ASSERT_LT(width + kTestWidth, kCanvasSize.width());
|
| - const uint32* buffer = static_cast<const uint32*>(
|
| - surface->peekPixels(NULL, NULL));
|
| + ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width());
|
| + const uint32* buffer =
|
| + static_cast<const uint32*>(surface->peekPixels(nullptr, nullptr));
|
| ASSERT_NE(nullptr, buffer);
|
| + TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(),
|
| + kCanvasSize.height());
|
| + {
|
| +#if !defined(OS_CHROMEOS)
|
| + // TODO(dschuyler): On ChromeOS text draws above the GetStringSize rect.
|
| + SCOPED_TRACE("TextDoesntClip Top Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(),
|
| + kTestSize);
|
| +#endif
|
| + }
|
| + {
|
| + SCOPED_TRACE("TextDoesntClip Bottom Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0,
|
| + kTestSize + string_size.height(),
|
| + kCanvasSize.width(), kTestSize);
|
| + }
|
| + {
|
| + SCOPED_TRACE("TextDoesntClip Left Side");
|
| +#if defined(OS_WIN)
|
| + // TODO(dschuyler): On Windows XP the Unicode test draws to the left edge
|
| + // as if it is ignoring the SetDisplayRect shift by kTestSize. This
|
| + // appears to be a preexisting issue that wasn't revealed by the prior
|
| + // unit tests.
|
| +#elif defined(OS_MACOSX)
|
| + // TODO(dschuyler): On Windows (non-XP) and Mac smoothing draws left of
|
| + // text. his appears to be a preexisting issue that wasn't revealed by
|
| + // the prior unit tests.
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize, kTestSize - 1,
|
| + string_size.height());
|
| +#else
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize, kTestSize,
|
| + string_size.height());
|
| +#endif
|
| + }
|
| + {
|
| + SCOPED_TRACE("TextDoesntClip Right Side");
|
| +#if !defined(OS_MACOSX)
|
| + // TODO(dschuyler): On Mac text draws to right of GetStringSize. This
|
| + // appears to be a preexisting issue that wasn't revealed by the prior
|
| + // unit tests.
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE,
|
| + kTestSize + string_size.width(), kTestSize,
|
| + kTestSize, string_size.height());
|
| +#endif
|
| + }
|
| + }
|
| +}
|
|
|
| - for (int y = 0; y < kCanvasSize.height(); ++y) {
|
| - // Allow one column of anti-aliased pixels past the expected width.
|
| - SkColor color = buffer[width + y * kCanvasSize.width()];
|
| - EXPECT_LT(220U, color_utils::GetLuminanceForColor(color)) << string;
|
| - for (int x = 1; x < kTestWidth; ++x) {
|
| - color = buffer[width + x + y * kCanvasSize.width()];
|
| - EXPECT_EQ(SK_ColorWHITE, color) << string;
|
| - }
|
| +// Ensure that the text will clip to the display rect. Draws to a canvas and
|
| +// checks whether any pixel beyond the bounding rectangle is colored.
|
| +TEST_F(RenderTextTest, TextDoesClip) {
|
| + const wchar_t* kTestStrings[] = {L"TEST", L"W", L"WWWW", L"gAXAXWWWW"};
|
| + const Size kCanvasSize(300, 50);
|
| + const int kTestSize = 10;
|
| +
|
| + skia::RefPtr<SkSurface> surface = skia::AdoptRef(
|
| + SkSurface::NewRasterN32Premul(kCanvasSize.width(), kCanvasSize.height()));
|
| + scoped_ptr<Canvas> canvas(
|
| + Canvas::CreateCanvasWithoutScaling(surface->getCanvas(), 1.0f));
|
| + scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
|
| + render_text->SetHorizontalAlignment(ALIGN_LEFT);
|
| + render_text->SetColor(SK_ColorBLACK);
|
| +
|
| + for (auto string : kTestStrings) {
|
| + surface->getCanvas()->clear(SK_ColorWHITE);
|
| + render_text->SetText(WideToUTF16(string));
|
| + const Size string_size = render_text->GetStringSize();
|
| + int fake_width = string_size.width() / 2;
|
| + int fake_height = string_size.height() / 2;
|
| + render_text->SetDisplayRect(
|
| + Rect(kTestSize, kTestSize, fake_width, fake_height));
|
| + render_text->set_clip_to_display_rect(true);
|
| + render_text->Draw(canvas.get());
|
| + ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width());
|
| + const uint32* buffer =
|
| + static_cast<const uint32*>(surface->peekPixels(nullptr, nullptr));
|
| + ASSERT_NE(nullptr, buffer);
|
| + TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(),
|
| + kCanvasSize.height());
|
| + {
|
| + SCOPED_TRACE("TextDoesClip Top Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(),
|
| + kTestSize);
|
| + }
|
| +
|
| + {
|
| + SCOPED_TRACE("TextDoesClip Bottom Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize + fake_height,
|
| + kCanvasSize.width(), kTestSize);
|
| + }
|
| + {
|
| + SCOPED_TRACE("TextDoesClip Left Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize, kTestSize,
|
| + fake_height);
|
| + }
|
| + {
|
| + SCOPED_TRACE("TextDoesClip Right Side");
|
| + rect_buffer.EnsureSolidRect(SK_ColorWHITE, kTestSize + fake_width,
|
| + kTestSize, kTestSize, fake_height);
|
| }
|
| }
|
| }
|
|
|