| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
| 6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
| 7 #include <algorithm> | 10 #include <algorithm> |
| 8 | 11 |
| 9 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
| 10 #include "base/i18n/break_iterator.h" | 13 #include "base/i18n/break_iterator.h" |
| 14 #include "base/macros.h" |
| 11 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
| 13 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 14 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 20 #include "build/build_config.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "third_party/skia/include/core/SkSurface.h" | 22 #include "third_party/skia/include/core/SkSurface.h" |
| 18 #include "ui/gfx/break_list.h" | 23 #include "ui/gfx/break_list.h" |
| 19 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/color_utils.h" | 25 #include "ui/gfx/color_utils.h" |
| 21 #include "ui/gfx/font.h" | 26 #include "ui/gfx/font.h" |
| 22 #include "ui/gfx/geometry/point.h" | 27 #include "ui/gfx/geometry/point.h" |
| 23 #include "ui/gfx/geometry/point_f.h" | 28 #include "ui/gfx/geometry/point_f.h" |
| 24 #include "ui/gfx/range/range.h" | 29 #include "ui/gfx/range/range.h" |
| 25 #include "ui/gfx/range/range_f.h" | 30 #include "ui/gfx/range/range_f.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 } | 154 } |
| 150 | 155 |
| 151 void GetDecorationLogAndReset(std::vector<DecorationLog>* decoration_log) { | 156 void GetDecorationLogAndReset(std::vector<DecorationLog>* decoration_log) { |
| 152 decoration_log_.swap(*decoration_log); | 157 decoration_log_.swap(*decoration_log); |
| 153 decoration_log_.clear(); | 158 decoration_log_.clear(); |
| 154 } | 159 } |
| 155 | 160 |
| 156 private: | 161 private: |
| 157 // internal::SkiaTextRenderer: | 162 // internal::SkiaTextRenderer: |
| 158 void DrawPosText(const SkPoint* pos, | 163 void DrawPosText(const SkPoint* pos, |
| 159 const uint16* glyphs, | 164 const uint16_t* glyphs, |
| 160 size_t glyph_count) override { | 165 size_t glyph_count) override { |
| 161 TextLog log_entry; | 166 TextLog log_entry; |
| 162 log_entry.glyph_count = glyph_count; | 167 log_entry.glyph_count = glyph_count; |
| 163 if (glyph_count > 0) { | 168 if (glyph_count > 0) { |
| 164 log_entry.origin = | 169 log_entry.origin = |
| 165 PointF(SkScalarToFloat(pos[0].x()), SkScalarToFloat(pos[0].y())); | 170 PointF(SkScalarToFloat(pos[0].x()), SkScalarToFloat(pos[0].y())); |
| 166 for (size_t i = 1U; i < glyph_count; ++i) { | 171 for (size_t i = 1U; i < glyph_count; ++i) { |
| 167 log_entry.origin.SetToMin( | 172 log_entry.origin.SetToMin( |
| 168 PointF(SkScalarToFloat(pos[i].x()), SkScalarToFloat(pos[i].y()))); | 173 PointF(SkScalarToFloat(pos[i].x()), SkScalarToFloat(pos[i].y()))); |
| 169 } | 174 } |
| (...skipping 2436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2606 text_log[0].glyph_count); | 2611 text_log[0].glyph_count); |
| 2607 EXPECT_EQ(run_list->runs()[run_list->logical_to_visual(1)]->glyph_count, | 2612 EXPECT_EQ(run_list->runs()[run_list->logical_to_visual(1)]->glyph_count, |
| 2608 text_log[1].glyph_count); | 2613 text_log[1].glyph_count); |
| 2609 EXPECT_LT(text_log[0].origin.x(), text_log[1].origin.x()); | 2614 EXPECT_LT(text_log[0].origin.x(), text_log[1].origin.x()); |
| 2610 } | 2615 } |
| 2611 } | 2616 } |
| 2612 | 2617 |
| 2613 // Test TextRunHarfBuzz's cluster finding logic. | 2618 // Test TextRunHarfBuzz's cluster finding logic. |
| 2614 TEST_F(RenderTextTest, HarfBuzz_Clusters) { | 2619 TEST_F(RenderTextTest, HarfBuzz_Clusters) { |
| 2615 struct { | 2620 struct { |
| 2616 uint32 glyph_to_char[4]; | 2621 uint32_t glyph_to_char[4]; |
| 2617 Range chars[4]; | 2622 Range chars[4]; |
| 2618 Range glyphs[4]; | 2623 Range glyphs[4]; |
| 2619 bool is_rtl; | 2624 bool is_rtl; |
| 2620 } cases[] = { | 2625 } cases[] = { |
| 2621 { // From string "A B C D" to glyphs "a b c d". | 2626 { // From string "A B C D" to glyphs "a b c d". |
| 2622 { 0, 1, 2, 3 }, | 2627 { 0, 1, 2, 3 }, |
| 2623 { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) }, | 2628 { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) }, |
| 2624 { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) }, | 2629 { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) }, |
| 2625 false | 2630 false |
| 2626 }, | 2631 }, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2694 auto first_grapheme_bounds = run->GetGraphemeBounds(iter, 0); | 2699 auto first_grapheme_bounds = run->GetGraphemeBounds(iter, 0); |
| 2695 EXPECT_EQ(first_grapheme_bounds, run->GetGraphemeBounds(iter, 1)); | 2700 EXPECT_EQ(first_grapheme_bounds, run->GetGraphemeBounds(iter, 1)); |
| 2696 auto second_grapheme_bounds = run->GetGraphemeBounds(iter, 2); | 2701 auto second_grapheme_bounds = run->GetGraphemeBounds(iter, 2); |
| 2697 EXPECT_EQ(first_grapheme_bounds.end(), second_grapheme_bounds.start()); | 2702 EXPECT_EQ(first_grapheme_bounds.end(), second_grapheme_bounds.start()); |
| 2698 } | 2703 } |
| 2699 } | 2704 } |
| 2700 | 2705 |
| 2701 // Test the partition of a multi-grapheme cluster into grapheme ranges. | 2706 // Test the partition of a multi-grapheme cluster into grapheme ranges. |
| 2702 TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) { | 2707 TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) { |
| 2703 struct { | 2708 struct { |
| 2704 uint32 glyph_to_char[2]; | 2709 uint32_t glyph_to_char[2]; |
| 2705 Range bounds[4]; | 2710 Range bounds[4]; |
| 2706 bool is_rtl; | 2711 bool is_rtl; |
| 2707 } cases[] = { | 2712 } cases[] = { |
| 2708 { // From string "A B C D" to glyphs "a bcd". | 2713 { // From string "A B C D" to glyphs "a bcd". |
| 2709 { 0, 1 }, | 2714 { 0, 1 }, |
| 2710 { Range(0, 10), Range(10, 13), Range(13, 17), Range(17, 20) }, | 2715 { Range(0, 10), Range(10, 13), Range(13, 17), Range(17, 20) }, |
| 2711 false | 2716 false |
| 2712 }, | 2717 }, |
| 2713 { // From string "A B C D" to glyphs "ab cd". | 2718 { // From string "A B C D" to glyphs "ab cd". |
| 2714 { 0, 2 }, | 2719 { 0, 2 }, |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 render_text->ApplyBaselineStyle(SUBSCRIPT, Range(7, 8)); | 3033 render_text->ApplyBaselineStyle(SUBSCRIPT, Range(7, 8)); |
| 3029 render_text->SetStyle(BOLD, true); | 3034 render_text->SetStyle(BOLD, true); |
| 3030 render_text->SetDisplayRect( | 3035 render_text->SetDisplayRect( |
| 3031 Rect(kTestSize, kTestSize, string_size.width(), string_size.height())); | 3036 Rect(kTestSize, kTestSize, string_size.width(), string_size.height())); |
| 3032 // Allow the RenderText to paint outside of its display rect. | 3037 // Allow the RenderText to paint outside of its display rect. |
| 3033 render_text->set_clip_to_display_rect(false); | 3038 render_text->set_clip_to_display_rect(false); |
| 3034 ASSERT_LE(string_size.width() + kTestSize * 2, kCanvasSize.width()); | 3039 ASSERT_LE(string_size.width() + kTestSize * 2, kCanvasSize.width()); |
| 3035 | 3040 |
| 3036 render_text->Draw(&canvas); | 3041 render_text->Draw(&canvas); |
| 3037 ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width()); | 3042 ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width()); |
| 3038 const uint32* buffer = | 3043 const uint32_t* buffer = |
| 3039 static_cast<const uint32*>(surface->peekPixels(nullptr, nullptr)); | 3044 static_cast<const uint32_t*>(surface->peekPixels(nullptr, nullptr)); |
| 3040 ASSERT_NE(nullptr, buffer); | 3045 ASSERT_NE(nullptr, buffer); |
| 3041 TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(), | 3046 TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(), |
| 3042 kCanvasSize.height()); | 3047 kCanvasSize.height()); |
| 3043 { | 3048 { |
| 3044 #if !defined(OS_CHROMEOS) | 3049 #if !defined(OS_CHROMEOS) |
| 3045 // TODO(dschuyler): On ChromeOS text draws above the GetStringSize rect. | 3050 // TODO(dschuyler): On ChromeOS text draws above the GetStringSize rect. |
| 3046 SCOPED_TRACE("TextDoesntClip Top Side"); | 3051 SCOPED_TRACE("TextDoesntClip Top Side"); |
| 3047 rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(), | 3052 rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(), |
| 3048 kTestSize); | 3053 kTestSize); |
| 3049 #endif | 3054 #endif |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3104 surface->getCanvas()->clear(SK_ColorWHITE); | 3109 surface->getCanvas()->clear(SK_ColorWHITE); |
| 3105 render_text->SetText(WideToUTF16(string)); | 3110 render_text->SetText(WideToUTF16(string)); |
| 3106 const Size string_size = render_text->GetStringSize(); | 3111 const Size string_size = render_text->GetStringSize(); |
| 3107 int fake_width = string_size.width() / 2; | 3112 int fake_width = string_size.width() / 2; |
| 3108 int fake_height = string_size.height() / 2; | 3113 int fake_height = string_size.height() / 2; |
| 3109 render_text->SetDisplayRect( | 3114 render_text->SetDisplayRect( |
| 3110 Rect(kTestSize, kTestSize, fake_width, fake_height)); | 3115 Rect(kTestSize, kTestSize, fake_width, fake_height)); |
| 3111 render_text->set_clip_to_display_rect(true); | 3116 render_text->set_clip_to_display_rect(true); |
| 3112 render_text->Draw(&canvas); | 3117 render_text->Draw(&canvas); |
| 3113 ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width()); | 3118 ASSERT_LT(string_size.width() + kTestSize, kCanvasSize.width()); |
| 3114 const uint32* buffer = | 3119 const uint32_t* buffer = |
| 3115 static_cast<const uint32*>(surface->peekPixels(nullptr, nullptr)); | 3120 static_cast<const uint32_t*>(surface->peekPixels(nullptr, nullptr)); |
| 3116 ASSERT_NE(nullptr, buffer); | 3121 ASSERT_NE(nullptr, buffer); |
| 3117 TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(), | 3122 TestRectangleBuffer rect_buffer(string, buffer, kCanvasSize.width(), |
| 3118 kCanvasSize.height()); | 3123 kCanvasSize.height()); |
| 3119 { | 3124 { |
| 3120 SCOPED_TRACE("TextDoesClip Top Side"); | 3125 SCOPED_TRACE("TextDoesClip Top Side"); |
| 3121 rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(), | 3126 rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(), |
| 3122 kTestSize); | 3127 kTestSize); |
| 3123 } | 3128 } |
| 3124 | 3129 |
| 3125 { | 3130 { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3194 backend[i]->SetColor(SK_ColorRED); | 3199 backend[i]->SetColor(SK_ColorRED); |
| 3195 test_api.DrawVisualText(&renderer); | 3200 test_api.DrawVisualText(&renderer); |
| 3196 | 3201 |
| 3197 renderer.GetTextLogAndReset(&text_log); | 3202 renderer.GetTextLogAndReset(&text_log); |
| 3198 EXPECT_EQ(1u, text_log.size()); | 3203 EXPECT_EQ(1u, text_log.size()); |
| 3199 EXPECT_EQ(SK_ColorRED, text_log[0].color); | 3204 EXPECT_EQ(SK_ColorRED, text_log[0].color); |
| 3200 } | 3205 } |
| 3201 } | 3206 } |
| 3202 | 3207 |
| 3203 } // namespace gfx | 3208 } // namespace gfx |
| OLD | NEW |