OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 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/CachingWordShaper.h" | 5 #include "platform/fonts/shaping/CachingWordShaper.h" |
6 | 6 |
7 #include "platform/fonts/CharacterRange.h" | 7 #include "platform/fonts/CharacterRange.h" |
8 #include "platform/fonts/FontCache.h" | 8 #include "platform/fonts/FontCache.h" |
9 #include "platform/fonts/GlyphBuffer.h" | 9 #include "platform/fonts/GlyphBuffer.h" |
10 #include "platform/fonts/shaping/CachingWordShapeIterator.h" | 10 #include "platform/fonts/shaping/CachingWordShapeIterator.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 ASSERT_FALSE(iterator.next(&result)); | 109 ASSERT_FALSE(iterator.next(&result)); |
110 } | 110 } |
111 | 111 |
112 // Tests that filling a glyph buffer for a specific range returns the same | 112 // Tests that filling a glyph buffer for a specific range returns the same |
113 // results when shaping word by word as when shaping the full run in one go. | 113 // results when shaping word by word as when shaping the full run in one go. |
114 TEST_F(CachingWordShaperTest, CommonAccentLeftToRightFillGlyphBuffer) { | 114 TEST_F(CachingWordShaperTest, CommonAccentLeftToRightFillGlyphBuffer) { |
115 // "/. ." with an accent mark over the first dot. | 115 // "/. ." with an accent mark over the first dot. |
116 const UChar str[] = {0x2F, 0x301, 0x2E, 0x20, 0x2E, 0x0}; | 116 const UChar str[] = {0x2F, 0x301, 0x2E, 0x20, 0x2E, 0x0}; |
117 TextRun textRun(str, 5); | 117 TextRun textRun(str, 5); |
118 | 118 |
119 CachingWordShaper shaper(cache.get()); | 119 CachingWordShaper shaper(font, cache.get()); |
120 GlyphBuffer glyphBuffer; | 120 GlyphBuffer glyphBuffer; |
121 shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 0, 3); | 121 shaper.fillGlyphBuffer(textRun, &glyphBuffer, 0, 3); |
122 | 122 |
123 std::unique_ptr<ShapeCache> referenceCache = WTF::makeUnique<ShapeCache>(); | 123 std::unique_ptr<ShapeCache> referenceCache = WTF::makeUnique<ShapeCache>(); |
124 CachingWordShaper referenceShaper(referenceCache.get()); | 124 CachingWordShaper referenceShaper(font, referenceCache.get()); |
125 GlyphBuffer referenceGlyphBuffer; | 125 GlyphBuffer referenceGlyphBuffer; |
126 font.setCanShapeWordByWordForTesting(false); | 126 font.setCanShapeWordByWordForTesting(false); |
127 referenceShaper.fillGlyphBuffer(&font, textRun, fallbackFonts, | 127 referenceShaper.fillGlyphBuffer(textRun, &referenceGlyphBuffer, 0, 3); |
128 &referenceGlyphBuffer, 0, 3); | |
129 | 128 |
130 ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0)); | 129 ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0)); |
131 ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1)); | 130 ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1)); |
132 ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2)); | 131 ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2)); |
133 } | 132 } |
134 | 133 |
135 // Tests that filling a glyph buffer for a specific range returns the same | 134 // Tests that filling a glyph buffer for a specific range returns the same |
136 // results when shaping word by word as when shaping the full run in one go. | 135 // results when shaping word by word as when shaping the full run in one go. |
137 TEST_F(CachingWordShaperTest, CommonAccentRightToLeftFillGlyphBuffer) { | 136 TEST_F(CachingWordShaperTest, CommonAccentRightToLeftFillGlyphBuffer) { |
138 // "[] []" with an accent mark over the last square bracket. | 137 // "[] []" with an accent mark over the last square bracket. |
139 const UChar str[] = {0x5B, 0x5D, 0x20, 0x5B, 0x301, 0x5D, 0x0}; | 138 const UChar str[] = {0x5B, 0x5D, 0x20, 0x5B, 0x301, 0x5D, 0x0}; |
140 TextRun textRun(str, 6); | 139 TextRun textRun(str, 6); |
141 textRun.setDirection(TextDirection::kRtl); | 140 textRun.setDirection(TextDirection::kRtl); |
142 | 141 |
143 CachingWordShaper shaper(cache.get()); | 142 CachingWordShaper shaper(font, cache.get()); |
144 GlyphBuffer glyphBuffer; | 143 GlyphBuffer glyphBuffer; |
145 shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 1, 6); | 144 shaper.fillGlyphBuffer(textRun, &glyphBuffer, 1, 6); |
146 | 145 |
147 std::unique_ptr<ShapeCache> referenceCache = WTF::makeUnique<ShapeCache>(); | 146 std::unique_ptr<ShapeCache> referenceCache = WTF::makeUnique<ShapeCache>(); |
148 CachingWordShaper referenceShaper(referenceCache.get()); | 147 CachingWordShaper referenceShaper(font, referenceCache.get()); |
149 GlyphBuffer referenceGlyphBuffer; | 148 GlyphBuffer referenceGlyphBuffer; |
150 font.setCanShapeWordByWordForTesting(false); | 149 font.setCanShapeWordByWordForTesting(false); |
151 referenceShaper.fillGlyphBuffer(&font, textRun, fallbackFonts, | 150 referenceShaper.fillGlyphBuffer(textRun, &referenceGlyphBuffer, 1, 6); |
152 &referenceGlyphBuffer, 1, 6); | |
153 | 151 |
154 ASSERT_EQ(5u, referenceGlyphBuffer.size()); | 152 ASSERT_EQ(5u, referenceGlyphBuffer.size()); |
155 ASSERT_EQ(referenceGlyphBuffer.size(), glyphBuffer.size()); | 153 ASSERT_EQ(referenceGlyphBuffer.size(), glyphBuffer.size()); |
156 | 154 |
157 ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0)); | 155 ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0)); |
158 ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1)); | 156 ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1)); |
159 ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2)); | 157 ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2)); |
160 ASSERT_EQ(referenceGlyphBuffer.glyphAt(3), glyphBuffer.glyphAt(3)); | 158 ASSERT_EQ(referenceGlyphBuffer.glyphAt(3), glyphBuffer.glyphAt(3)); |
161 ASSERT_EQ(referenceGlyphBuffer.glyphAt(4), glyphBuffer.glyphAt(4)); | 159 ASSERT_EQ(referenceGlyphBuffer.glyphAt(4), glyphBuffer.glyphAt(4)); |
162 } | 160 } |
163 | 161 |
164 // Tests that runs with zero glyphs (the ZWJ non-printable character in this | 162 // Tests that runs with zero glyphs (the ZWJ non-printable character in this |
165 // case) are handled correctly. This test passes if it does not cause a crash. | 163 // case) are handled correctly. This test passes if it does not cause a crash. |
166 TEST_F(CachingWordShaperTest, SubRunWithZeroGlyphs) { | 164 TEST_F(CachingWordShaperTest, SubRunWithZeroGlyphs) { |
167 // "Foo ‌ bar" | 165 // "Foo ‌ bar" |
168 const UChar str[] = {0x46, 0x6F, 0x6F, 0x20, 0x200C, | 166 const UChar str[] = {0x46, 0x6F, 0x6F, 0x20, 0x200C, |
169 0x20, 0x62, 0x61, 0x71, 0x0}; | 167 0x20, 0x62, 0x61, 0x71, 0x0}; |
170 TextRun textRun(str, 9); | 168 TextRun textRun(str, 9); |
171 | 169 |
172 CachingWordShaper shaper(cache.get()); | 170 CachingWordShaper shaper(font, cache.get()); |
173 FloatRect glyphBounds; | 171 FloatRect glyphBounds; |
174 ASSERT_GT(shaper.width(&font, textRun, nullptr, &glyphBounds), 0); | 172 ASSERT_GT(shaper.width(textRun, nullptr, &glyphBounds), 0); |
175 | 173 |
176 GlyphBuffer glyphBuffer; | 174 GlyphBuffer glyphBuffer; |
177 shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 0, 8); | 175 shaper.fillGlyphBuffer(textRun, &glyphBuffer, 0, 8); |
178 | 176 |
179 shaper.getCharacterRange(&font, textRun, 0, 8); | 177 shaper.getCharacterRange(textRun, 0, 8); |
180 } | 178 } |
181 | 179 |
182 TEST_F(CachingWordShaperTest, SegmentCJKByCharacter) { | 180 TEST_F(CachingWordShaperTest, SegmentCJKByCharacter) { |
183 const UChar str[] = {0x56FD, 0x56FD, // CJK Unified Ideograph | 181 const UChar str[] = {0x56FD, 0x56FD, // CJK Unified Ideograph |
184 'a', 'b', | 182 'a', 'b', |
185 0x56FD, // CJK Unified Ideograph | 183 0x56FD, // CJK Unified Ideograph |
186 'x', 'y', 'z', | 184 'x', 'y', 'z', |
187 0x3042, // HIRAGANA LETTER A | 185 0x3042, // HIRAGANA LETTER A |
188 0x56FD, // CJK Unified Ideograph | 186 0x56FD, // CJK Unified Ideograph |
189 0x0}; | 187 0x0}; |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 // using code point such as U+3042, but it'd fallback to system | 433 // using code point such as U+3042, but it'd fallback to system |
436 // fonts as the glyph is missing. | 434 // fonts as the glyph is missing. |
437 0x0}; | 435 0x0}; |
438 TextRun textRun(str, 1); | 436 TextRun textRun(str, 1); |
439 | 437 |
440 fontDescription.setOrientation(FontOrientation::VerticalMixed); | 438 fontDescription.setOrientation(FontOrientation::VerticalMixed); |
441 Font verticalMixedFont = Font(fontDescription); | 439 Font verticalMixedFont = Font(fontDescription); |
442 verticalMixedFont.update(nullptr); | 440 verticalMixedFont.update(nullptr); |
443 ASSERT_TRUE(verticalMixedFont.canShapeWordByWord()); | 441 ASSERT_TRUE(verticalMixedFont.canShapeWordByWord()); |
444 | 442 |
445 CachingWordShaper shaper(cache.get()); | 443 CachingWordShaper shaper(verticalMixedFont, cache.get()); |
446 FloatRect glyphBounds; | 444 FloatRect glyphBounds; |
447 HashSet<const SimpleFontData*> fallbackFonts; | 445 HashSet<const SimpleFontData*> fallbackFonts; |
448 ASSERT_GT( | 446 ASSERT_GT( |
449 shaper.width(&verticalMixedFont, textRun, &fallbackFonts, &glyphBounds), | 447 shaper.width(textRun, &fallbackFonts, &glyphBounds), |
450 0); | 448 0); |
451 EXPECT_EQ(0u, fallbackFonts.size()); | 449 EXPECT_EQ(0u, fallbackFonts.size()); |
452 } | 450 } |
453 | 451 |
454 TEST_F(CachingWordShaperTest, GlyphBoundsWithSpaces) { | 452 TEST_F(CachingWordShaperTest, GlyphBoundsWithSpaces) { |
455 CachingWordShaper shaper(cache.get()); | 453 CachingWordShaper shaper(font, cache.get()); |
456 | 454 |
457 TextRun periods(reinterpret_cast<const LChar*>(".........."), 10); | 455 TextRun periods(reinterpret_cast<const LChar*>(".........."), 10); |
458 FloatRect periodsGlyphBounds; | 456 FloatRect periodsGlyphBounds; |
459 float periodsWidth = | 457 float periodsWidth = shaper.width(periods, nullptr, &periodsGlyphBounds); |
460 shaper.width(&font, periods, nullptr, &periodsGlyphBounds); | |
461 | 458 |
462 TextRun periodsAndSpaces( | 459 TextRun periodsAndSpaces( |
463 reinterpret_cast<const LChar*>(". . . . . . . . . ."), 19); | 460 reinterpret_cast<const LChar*>(". . . . . . . . . ."), 19); |
464 FloatRect periodsAndSpacesGlyphBounds; | 461 FloatRect periodsAndSpacesGlyphBounds; |
465 float periodsAndSpacesWidth = shaper.width(&font, periodsAndSpaces, nullptr, | 462 float periodsAndSpacesWidth = shaper.width(periodsAndSpaces, nullptr, |
466 &periodsAndSpacesGlyphBounds); | 463 &periodsAndSpacesGlyphBounds); |
467 | 464 |
468 // The total width of periods and spaces should be longer than the width of | 465 // The total width of periods and spaces should be longer than the width of |
469 // periods alone. | 466 // periods alone. |
470 ASSERT_GT(periodsAndSpacesWidth, periodsWidth); | 467 ASSERT_GT(periodsAndSpacesWidth, periodsWidth); |
471 | 468 |
472 // The glyph bounds of periods and spaces should be longer than the glyph | 469 // The glyph bounds of periods and spaces should be longer than the glyph |
473 // bounds of periods alone. | 470 // bounds of periods alone. |
474 ASSERT_GT(periodsAndSpacesGlyphBounds.width(), periodsGlyphBounds.width()); | 471 ASSERT_GT(periodsAndSpacesGlyphBounds.width(), periodsGlyphBounds.width()); |
475 } | 472 } |
476 | 473 |
477 } // namespace blink | 474 } // namespace blink |
OLD | NEW |