| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "platform/fonts/shaping/ShapeResultBloberizer.h" | 5 #include "platform/fonts/shaping/ShapeResultBloberizer.h" |
| 6 | 6 |
| 7 #include "platform/fonts/CharacterRange.h" |
| 7 #include "platform/fonts/Font.h" | 8 #include "platform/fonts/Font.h" |
| 8 #include "platform/fonts/SimpleFontData.h" | 9 #include "platform/fonts/SimpleFontData.h" |
| 9 #include "platform/fonts/opentype/OpenTypeVerticalData.h" | 10 #include "platform/fonts/opentype/OpenTypeVerticalData.h" |
| 11 #include "platform/fonts/shaping/CachingWordShaper.h" |
| 10 #include "platform/fonts/shaping/ShapeResultTestInfo.h" | 12 #include "platform/fonts/shaping/ShapeResultTestInfo.h" |
| 11 #include "platform/wtf/Optional.h" | 13 #include "platform/wtf/Optional.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 15 |
| 14 namespace blink { | 16 namespace blink { |
| 15 | 17 |
| 16 namespace { | 18 namespace { |
| 17 | 19 |
| 18 // Minimal TestSimpleFontData implementation. | 20 // Minimal TestSimpleFontData implementation. |
| 19 // Font has no glyphs, but that's okay. | 21 // Font has no glyphs, but that's okay. |
| 20 class TestSimpleFontData : public SimpleFontData { | 22 class TestSimpleFontData : public SimpleFontData { |
| 21 public: | 23 public: |
| 22 static PassRefPtr<TestSimpleFontData> Create(bool force_rotation = false) { | 24 static PassRefPtr<TestSimpleFontData> Create(bool force_rotation = false) { |
| 23 FontPlatformData platform_data( | 25 FontPlatformData platform_data( |
| 24 SkTypeface::MakeDefault(), nullptr, 10, false, false, | 26 SkTypeface::MakeDefault(), nullptr, 10, false, false, |
| 25 force_rotation ? FontOrientation::kVerticalUpright | 27 force_rotation ? FontOrientation::kVerticalUpright |
| 26 : FontOrientation::kHorizontal); | 28 : FontOrientation::kHorizontal); |
| 27 RefPtr<OpenTypeVerticalData> vertical_data( | 29 RefPtr<OpenTypeVerticalData> vertical_data( |
| 28 force_rotation ? OpenTypeVerticalData::Create(platform_data) : nullptr); | 30 force_rotation ? OpenTypeVerticalData::Create(platform_data) : nullptr); |
| 29 return AdoptRef( | 31 return AdoptRef( |
| 30 new TestSimpleFontData(platform_data, std::move(vertical_data))); | 32 new TestSimpleFontData(platform_data, std::move(vertical_data))); |
| 31 } | 33 } |
| 32 | 34 |
| 33 private: | 35 private: |
| 34 TestSimpleFontData(const FontPlatformData& platform_data, | 36 TestSimpleFontData(const FontPlatformData& platform_data, |
| 35 PassRefPtr<OpenTypeVerticalData> vertical_data) | 37 PassRefPtr<OpenTypeVerticalData> vertical_data) |
| 36 : SimpleFontData(platform_data, std::move(vertical_data)) {} | 38 : SimpleFontData(platform_data, std::move(vertical_data)) {} |
| 37 }; | 39 }; |
| 38 | 40 |
| 41 class ShapeResultBloberizerTest : public ::testing::Test { |
| 42 protected: |
| 43 void SetUp() override { |
| 44 font_description.SetComputedSize(12.0); |
| 45 font_description.SetLocale(LayoutLocale::Get("en")); |
| 46 ASSERT_EQ(USCRIPT_LATIN, font_description.GetScript()); |
| 47 font_description.SetGenericFamily(FontDescription::kStandardFamily); |
| 48 |
| 49 font = Font(font_description); |
| 50 font.Update(nullptr); |
| 51 ASSERT_TRUE(font.CanShapeWordByWord()); |
| 52 fallback_fonts = nullptr; |
| 53 cache = WTF::MakeUnique<ShapeCache>(); |
| 54 } |
| 55 |
| 56 FontCachePurgePreventer font_cache_purge_preventer; |
| 57 FontDescription font_description; |
| 58 Font font; |
| 59 std::unique_ptr<ShapeCache> cache; |
| 60 HashSet<const SimpleFontData*>* fallback_fonts; |
| 61 unsigned start_index = 0; |
| 62 unsigned num_glyphs = 0; |
| 63 hb_script_t script = HB_SCRIPT_INVALID; |
| 64 }; |
| 65 |
| 39 } // anonymous namespace | 66 } // anonymous namespace |
| 40 | 67 |
| 41 TEST(ShapeResultBloberizerTest, StartsEmpty) { | 68 TEST_F(ShapeResultBloberizerTest, StartsEmpty) { |
| 42 Font font; | 69 Font font; |
| 43 ShapeResultBloberizer bloberizer(font, 1); | 70 ShapeResultBloberizer bloberizer(font, 1); |
| 44 | 71 |
| 45 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer), | 72 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer), |
| 46 nullptr); | 73 nullptr); |
| 47 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunGlyphs(bloberizer).size(), | 74 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunGlyphs(bloberizer).size(), |
| 48 0ul); | 75 0ul); |
| 49 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunOffsets(bloberizer).size(), | 76 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunOffsets(bloberizer).size(), |
| 50 0ul); | 77 0ul); |
| 51 EXPECT_FALSE( | 78 EXPECT_FALSE( |
| 52 ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer)); | 79 ShapeResultBloberizerTestInfo::HasPendingRunVerticalOffsets(bloberizer)); |
| 53 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), | 80 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), |
| 54 0ul); | 81 0ul); |
| 55 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); | 82 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); |
| 56 | 83 |
| 57 EXPECT_TRUE(bloberizer.Blobs().IsEmpty()); | 84 EXPECT_TRUE(bloberizer.Blobs().IsEmpty()); |
| 58 } | 85 } |
| 59 | 86 |
| 60 TEST(ShapeResultBloberizerTest, StoresGlyphsOffsets) { | 87 TEST_F(ShapeResultBloberizerTest, StoresGlyphsOffsets) { |
| 61 Font font; | 88 Font font; |
| 62 ShapeResultBloberizer bloberizer(font, 1); | 89 ShapeResultBloberizer bloberizer(font, 1); |
| 63 | 90 |
| 64 RefPtr<SimpleFontData> font1 = TestSimpleFontData::Create(); | 91 RefPtr<SimpleFontData> font1 = TestSimpleFontData::Create(); |
| 65 RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create(); | 92 RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create(); |
| 66 | 93 |
| 67 // 2 pending glyphs | 94 // 2 pending glyphs |
| 68 bloberizer.Add(42, font1.Get(), 10); | 95 bloberizer.Add(42, font1.Get(), 10); |
| 69 bloberizer.Add(43, font1.Get(), 15); | 96 bloberizer.Add(43, font1.Get(), 15); |
| 70 | 97 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 } | 137 } |
| 111 | 138 |
| 112 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), | 139 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), |
| 113 1ul); | 140 1ul); |
| 114 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); | 141 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); |
| 115 | 142 |
| 116 // flush everything (1 blob w/ 2 runs) | 143 // flush everything (1 blob w/ 2 runs) |
| 117 EXPECT_EQ(bloberizer.Blobs().size(), 1ul); | 144 EXPECT_EQ(bloberizer.Blobs().size(), 1ul); |
| 118 } | 145 } |
| 119 | 146 |
| 120 TEST(ShapeResultBloberizerTest, StoresGlyphsVerticalOffsets) { | 147 TEST_F(ShapeResultBloberizerTest, StoresGlyphsVerticalOffsets) { |
| 121 Font font; | 148 Font font; |
| 122 ShapeResultBloberizer bloberizer(font, 1); | 149 ShapeResultBloberizer bloberizer(font, 1); |
| 123 | 150 |
| 124 RefPtr<SimpleFontData> font1 = TestSimpleFontData::Create(); | 151 RefPtr<SimpleFontData> font1 = TestSimpleFontData::Create(); |
| 125 RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create(); | 152 RefPtr<SimpleFontData> font2 = TestSimpleFontData::Create(); |
| 126 | 153 |
| 127 // 2 pending glyphs | 154 // 2 pending glyphs |
| 128 bloberizer.Add(42, font1.Get(), FloatPoint(10, 0)); | 155 bloberizer.Add(42, font1.Get(), FloatPoint(10, 0)); |
| 129 bloberizer.Add(43, font1.Get(), FloatPoint(15, 0)); | 156 bloberizer.Add(43, font1.Get(), FloatPoint(15, 0)); |
| 130 | 157 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 } | 200 } |
| 174 | 201 |
| 175 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), | 202 EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer), |
| 176 1ul); | 203 1ul); |
| 177 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); | 204 EXPECT_EQ(ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer), 0ul); |
| 178 | 205 |
| 179 // flush everything (1 blob w/ 2 runs) | 206 // flush everything (1 blob w/ 2 runs) |
| 180 EXPECT_EQ(bloberizer.Blobs().size(), 1ul); | 207 EXPECT_EQ(bloberizer.Blobs().size(), 1ul); |
| 181 } | 208 } |
| 182 | 209 |
| 183 TEST(ShapeResultBloberizerTest, MixedBlobRotation) { | 210 TEST_F(ShapeResultBloberizerTest, MixedBlobRotation) { |
| 184 Font font; | 211 Font font; |
| 185 ShapeResultBloberizer bloberizer(font, 1); | 212 ShapeResultBloberizer bloberizer(font, 1); |
| 186 | 213 |
| 187 // Normal (horizontal) font. | 214 // Normal (horizontal) font. |
| 188 RefPtr<SimpleFontData> font_normal = TestSimpleFontData::Create(); | 215 RefPtr<SimpleFontData> font_normal = TestSimpleFontData::Create(); |
| 189 ASSERT_FALSE(font_normal->PlatformData().IsVerticalAnyUpright()); | 216 ASSERT_FALSE(font_normal->PlatformData().IsVerticalAnyUpright()); |
| 190 ASSERT_EQ(font_normal->VerticalData(), nullptr); | 217 ASSERT_EQ(font_normal->VerticalData(), nullptr); |
| 191 | 218 |
| 192 // Rotated (vertical upright) font. | 219 // Rotated (vertical upright) font. |
| 193 RefPtr<SimpleFontData> font_rotated = TestSimpleFontData::Create(true); | 220 RefPtr<SimpleFontData> font_rotated = TestSimpleFontData::Create(true); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 EXPECT_EQ(op.expected_pending_runs, | 255 EXPECT_EQ(op.expected_pending_runs, |
| 229 ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer)); | 256 ShapeResultBloberizerTestInfo::PendingBlobRunCount(bloberizer)); |
| 230 EXPECT_EQ(op.expected_committed_blobs, | 257 EXPECT_EQ(op.expected_committed_blobs, |
| 231 ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer)); | 258 ShapeResultBloberizerTestInfo::CommittedBlobCount(bloberizer)); |
| 232 } | 259 } |
| 233 | 260 |
| 234 // flush everything -> 4 blobs total | 261 // flush everything -> 4 blobs total |
| 235 EXPECT_EQ(4u, bloberizer.Blobs().size()); | 262 EXPECT_EQ(4u, bloberizer.Blobs().size()); |
| 236 } | 263 } |
| 237 | 264 |
| 265 // Tests that filling a glyph buffer for a specific range returns the same |
| 266 // results when shaping word by word as when shaping the full run in one go. |
| 267 TEST_F(ShapeResultBloberizerTest, CommonAccentLeftToRightFillGlyphBuffer) { |
| 268 // "/. ." with an accent mark over the first dot. |
| 269 const UChar kStr[] = {0x2F, 0x301, 0x2E, 0x20, 0x2E, 0x0}; |
| 270 TextRun text_run(kStr, 5); |
| 271 TextRunPaintInfo run_info(text_run); |
| 272 run_info.to = 3; |
| 273 |
| 274 ShapeResultBloberizer bloberizer(font, 1); |
| 275 CachingWordShaper word_shaper(font); |
| 276 ShapeResultBuffer buffer; |
| 277 word_shaper.FillResultBuffer(run_info, &buffer); |
| 278 bloberizer.FillGlyphs(run_info, buffer); |
| 279 |
| 280 Font reference_font(font_description); |
| 281 reference_font.Update(nullptr); |
| 282 reference_font.SetCanShapeWordByWordForTesting(false); |
| 283 |
| 284 ShapeResultBloberizer reference_bloberizer(reference_font, 1); |
| 285 CachingWordShaper reference_word_shaper(font); |
| 286 ShapeResultBuffer reference_buffer; |
| 287 reference_word_shaper.FillResultBuffer(run_info, &reference_buffer); |
| 288 reference_bloberizer.FillGlyphs(run_info, reference_buffer); |
| 289 |
| 290 const auto& glyphs = |
| 291 ShapeResultBloberizerTestInfo::PendingRunGlyphs(bloberizer); |
| 292 ASSERT_EQ(glyphs.size(), 3ul); |
| 293 const auto reference_glyphs = |
| 294 ShapeResultBloberizerTestInfo::PendingRunGlyphs(reference_bloberizer); |
| 295 ASSERT_EQ(reference_glyphs.size(), 3ul); |
| 296 |
| 297 EXPECT_EQ(reference_glyphs[0], glyphs[0]); |
| 298 EXPECT_EQ(reference_glyphs[1], glyphs[1]); |
| 299 EXPECT_EQ(reference_glyphs[2], glyphs[2]); |
| 300 } |
| 301 |
| 302 // Tests that filling a glyph buffer for a specific range returns the same |
| 303 // results when shaping word by word as when shaping the full run in one go. |
| 304 TEST_F(ShapeResultBloberizerTest, CommonAccentRightToLeftFillGlyphBuffer) { |
| 305 // "[] []" with an accent mark over the last square bracket. |
| 306 const UChar kStr[] = {0x5B, 0x5D, 0x20, 0x5B, 0x301, 0x5D, 0x0}; |
| 307 TextRun text_run(kStr, 6); |
| 308 text_run.SetDirection(TextDirection::kRtl); |
| 309 TextRunPaintInfo run_info(text_run); |
| 310 run_info.from = 1; |
| 311 |
| 312 ShapeResultBloberizer bloberizer(font, 1); |
| 313 CachingWordShaper word_shaper(font); |
| 314 ShapeResultBuffer buffer; |
| 315 word_shaper.FillResultBuffer(run_info, &buffer); |
| 316 bloberizer.FillGlyphs(run_info, buffer); |
| 317 |
| 318 Font reference_font(font_description); |
| 319 reference_font.Update(nullptr); |
| 320 reference_font.SetCanShapeWordByWordForTesting(false); |
| 321 |
| 322 ShapeResultBloberizer reference_bloberizer(reference_font, 1); |
| 323 CachingWordShaper reference_word_shaper(font); |
| 324 ShapeResultBuffer reference_buffer; |
| 325 reference_word_shaper.FillResultBuffer(run_info, &reference_buffer); |
| 326 reference_bloberizer.FillGlyphs(run_info, reference_buffer); |
| 327 |
| 328 const auto& glyphs = |
| 329 ShapeResultBloberizerTestInfo::PendingRunGlyphs(bloberizer); |
| 330 ASSERT_EQ(5u, glyphs.size()); |
| 331 const auto reference_glyphs = |
| 332 ShapeResultBloberizerTestInfo::PendingRunGlyphs(reference_bloberizer); |
| 333 ASSERT_EQ(5u, reference_glyphs.size()); |
| 334 |
| 335 EXPECT_EQ(reference_glyphs[0], glyphs[0]); |
| 336 EXPECT_EQ(reference_glyphs[1], glyphs[1]); |
| 337 EXPECT_EQ(reference_glyphs[2], glyphs[2]); |
| 338 EXPECT_EQ(reference_glyphs[3], glyphs[3]); |
| 339 EXPECT_EQ(reference_glyphs[4], glyphs[4]); |
| 340 } |
| 341 |
| 342 // Tests that runs with zero glyphs (the ZWJ non-printable character in this |
| 343 // case) are handled correctly. This test passes if it does not cause a crash. |
| 344 TEST_F(ShapeResultBloberizerTest, SubRunWithZeroGlyphs) { |
| 345 // "Foo ‌ bar" |
| 346 const UChar kStr[] = {0x46, 0x6F, 0x6F, 0x20, 0x200C, |
| 347 0x20, 0x62, 0x61, 0x71, 0x0}; |
| 348 TextRun text_run(kStr, 9); |
| 349 |
| 350 CachingWordShaper shaper(font); |
| 351 FloatRect glyph_bounds; |
| 352 ASSERT_GT(shaper.Width(text_run, nullptr, &glyph_bounds), 0); |
| 353 |
| 354 ShapeResultBloberizer bloberizer(font, 1); |
| 355 TextRunPaintInfo run_info(text_run); |
| 356 run_info.to = 8; |
| 357 |
| 358 CachingWordShaper word_shaper(font); |
| 359 ShapeResultBuffer buffer; |
| 360 word_shaper.FillResultBuffer(run_info, &buffer); |
| 361 bloberizer.FillGlyphs(run_info, buffer); |
| 362 |
| 363 shaper.GetCharacterRange(text_run, 0, 8); |
| 364 } |
| 365 |
| 238 } // namespace blink | 366 } // namespace blink |
| OLD | NEW |