Chromium Code Reviews| 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/HarfBuzzShaper.h" | 5 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
| 6 | 6 |
| 7 #include <unicode/uscript.h> | |
| 7 #include "platform/fonts/Font.h" | 8 #include "platform/fonts/Font.h" |
| 8 #include "platform/fonts/FontCache.h" | 9 #include "platform/fonts/FontCache.h" |
| 10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" | |
| 9 #include "platform/fonts/shaping/ShapeResultTestInfo.h" | 11 #include "platform/fonts/shaping/ShapeResultTestInfo.h" |
| 12 #include "platform/text/TextBreakIterator.h" | |
| 10 #include "platform/text/TextRun.h" | 13 #include "platform/text/TextRun.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "wtf/Vector.h" | 15 #include "wtf/Vector.h" |
| 13 #include <unicode/uscript.h> | |
| 14 | 16 |
| 15 namespace blink { | 17 namespace blink { |
| 16 | 18 |
| 17 class HarfBuzzShaperTest : public ::testing::Test { | 19 class HarfBuzzShaperTest : public ::testing::Test { |
| 18 protected: | 20 protected: |
| 19 void SetUp() override { | 21 void SetUp() override { |
| 20 fontDescription.setComputedSize(12.0); | 22 fontDescription.setComputedSize(12.0); |
| 21 font = Font(fontDescription); | 23 font = Font(fontDescription); |
| 22 font.update(nullptr); | 24 font.update(nullptr); |
| 23 } | 25 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 39 static inline String to16Bit(const char* text, unsigned length) { | 41 static inline String to16Bit(const char* text, unsigned length) { |
| 40 return String::make16BitFrom8BitSource(reinterpret_cast<const LChar*>(text), | 42 return String::make16BitFrom8BitSource(reinterpret_cast<const LChar*>(text), |
| 41 length); | 43 length); |
| 42 } | 44 } |
| 43 | 45 |
| 44 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) { | 46 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) { |
| 45 String latinCommon = to16Bit("ABC DEF.", 8); | 47 String latinCommon = to16Bit("ABC DEF.", 8); |
| 46 HarfBuzzShaper shaper(latinCommon.characters16(), 8); | 48 HarfBuzzShaper shaper(latinCommon.characters16(), 8); |
| 47 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 49 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 48 | 50 |
| 49 ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); | 51 EXPECT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); |
| 50 ASSERT_TRUE( | 52 ASSERT_TRUE( |
| 51 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 53 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 52 EXPECT_EQ(0u, startIndex); | 54 EXPECT_EQ(0u, startIndex); |
| 53 EXPECT_EQ(8u, numGlyphs); | 55 EXPECT_EQ(8u, numGlyphs); |
| 54 EXPECT_EQ(HB_SCRIPT_LATIN, script); | 56 EXPECT_EQ(HB_SCRIPT_LATIN, script); |
| 55 } | 57 } |
| 56 | 58 |
| 57 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) { | 59 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) { |
| 58 String leadingCommon = to16Bit("... test", 8); | 60 String leadingCommon = to16Bit("... test", 8); |
| 59 HarfBuzzShaper shaper(leadingCommon.characters16(), 8); | 61 HarfBuzzShaper shaper(leadingCommon.characters16(), 8); |
| 60 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 62 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 61 | 63 |
| 62 ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); | 64 EXPECT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); |
| 63 ASSERT_TRUE( | 65 ASSERT_TRUE( |
| 64 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 66 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 65 EXPECT_EQ(0u, startIndex); | 67 EXPECT_EQ(0u, startIndex); |
| 66 EXPECT_EQ(8u, numGlyphs); | 68 EXPECT_EQ(8u, numGlyphs); |
| 67 EXPECT_EQ(HB_SCRIPT_LATIN, script); | 69 EXPECT_EQ(HB_SCRIPT_LATIN, script); |
| 68 } | 70 } |
| 69 | 71 |
| 70 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) { | 72 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) { |
| 71 struct { | 73 struct { |
| 72 const char* name; | 74 const char* name; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 EXPECT_EQ(test.script, script) << test.name; | 107 EXPECT_EQ(test.script, script) << test.name; |
| 106 } | 108 } |
| 107 } | 109 } |
| 108 | 110 |
| 109 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) { | 111 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) { |
| 110 UChar devanagariCommonString[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29}; | 112 UChar devanagariCommonString[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29}; |
| 111 String devanagariCommonLatin(devanagariCommonString, 6); | 113 String devanagariCommonLatin(devanagariCommonString, 6); |
| 112 HarfBuzzShaper shaper(devanagariCommonLatin.characters16(), 6); | 114 HarfBuzzShaper shaper(devanagariCommonLatin.characters16(), 6); |
| 113 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 115 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 114 | 116 |
| 115 ASSERT_EQ(2u, testInfo(result)->numberOfRunsForTesting()); | 117 EXPECT_EQ(2u, testInfo(result)->numberOfRunsForTesting()); |
| 116 ASSERT_TRUE( | 118 ASSERT_TRUE( |
| 117 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 119 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 118 EXPECT_EQ(0u, startIndex); | 120 EXPECT_EQ(0u, startIndex); |
| 119 EXPECT_EQ(1u, numGlyphs); | 121 EXPECT_EQ(1u, numGlyphs); |
| 120 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); | 122 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); |
| 121 | 123 |
| 122 ASSERT_TRUE( | 124 ASSERT_TRUE( |
| 123 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); | 125 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); |
| 124 EXPECT_EQ(3u, startIndex); | 126 EXPECT_EQ(3u, startIndex); |
| 125 EXPECT_EQ(3u, numGlyphs); | 127 EXPECT_EQ(3u, numGlyphs); |
| 126 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); | 128 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); |
| 127 } | 129 } |
| 128 | 130 |
| 129 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) { | 131 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) { |
| 130 UChar devanagariCommonLatinString[] = {0x915, 0x94d, 0x930, 0x20, | 132 UChar devanagariCommonLatinString[] = {0x915, 0x94d, 0x930, 0x20, |
| 131 0x61, 0x62, 0x2E}; | 133 0x61, 0x62, 0x2E}; |
| 132 HarfBuzzShaper shaper(devanagariCommonLatinString, 7); | 134 HarfBuzzShaper shaper(devanagariCommonLatinString, 7); |
| 133 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 135 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 134 | 136 |
| 135 ASSERT_EQ(3u, testInfo(result)->numberOfRunsForTesting()); | 137 EXPECT_EQ(3u, testInfo(result)->numberOfRunsForTesting()); |
| 136 ASSERT_TRUE( | 138 ASSERT_TRUE( |
| 137 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 139 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 138 EXPECT_EQ(0u, startIndex); | 140 EXPECT_EQ(0u, startIndex); |
| 139 EXPECT_EQ(1u, numGlyphs); | 141 EXPECT_EQ(1u, numGlyphs); |
| 140 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); | 142 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); |
| 141 | 143 |
| 142 ASSERT_TRUE( | 144 ASSERT_TRUE( |
| 143 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); | 145 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); |
| 144 EXPECT_EQ(3u, startIndex); | 146 EXPECT_EQ(3u, startIndex); |
| 145 EXPECT_EQ(1u, numGlyphs); | 147 EXPECT_EQ(1u, numGlyphs); |
| 146 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); | 148 EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script); |
| 147 | 149 |
| 148 ASSERT_TRUE( | 150 ASSERT_TRUE( |
| 149 testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script)); | 151 testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script)); |
| 150 EXPECT_EQ(4u, startIndex); | 152 EXPECT_EQ(4u, startIndex); |
| 151 EXPECT_EQ(3u, numGlyphs); | 153 EXPECT_EQ(3u, numGlyphs); |
| 152 EXPECT_EQ(HB_SCRIPT_LATIN, script); | 154 EXPECT_EQ(HB_SCRIPT_LATIN, script); |
| 153 } | 155 } |
| 154 | 156 |
| 155 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) { | 157 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) { |
| 156 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; | 158 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; |
| 157 HarfBuzzShaper shaper(mixedString, 6); | 159 HarfBuzzShaper shaper(mixedString, 6); |
| 158 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 160 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 159 | 161 |
| 160 ASSERT_EQ(4u, testInfo(result)->numberOfRunsForTesting()); | 162 EXPECT_EQ(4u, testInfo(result)->numberOfRunsForTesting()); |
| 161 ASSERT_TRUE( | 163 ASSERT_TRUE( |
| 162 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 164 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 163 EXPECT_EQ(0u, startIndex); | 165 EXPECT_EQ(0u, startIndex); |
| 164 EXPECT_EQ(3u, numGlyphs); | 166 EXPECT_EQ(3u, numGlyphs); |
| 165 EXPECT_EQ(HB_SCRIPT_ARABIC, script); | 167 EXPECT_EQ(HB_SCRIPT_ARABIC, script); |
| 166 | 168 |
| 167 ASSERT_TRUE( | 169 ASSERT_TRUE( |
| 168 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); | 170 testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script)); |
| 169 EXPECT_EQ(3u, startIndex); | 171 EXPECT_EQ(3u, startIndex); |
| 170 EXPECT_EQ(1u, numGlyphs); | 172 EXPECT_EQ(1u, numGlyphs); |
| 171 EXPECT_EQ(HB_SCRIPT_THAI, script); | 173 EXPECT_EQ(HB_SCRIPT_THAI, script); |
| 172 | 174 |
| 173 ASSERT_TRUE( | 175 ASSERT_TRUE( |
| 174 testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script)); | 176 testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script)); |
| 175 EXPECT_EQ(4u, startIndex); | 177 EXPECT_EQ(4u, startIndex); |
| 176 EXPECT_EQ(1u, numGlyphs); | 178 EXPECT_EQ(1u, numGlyphs); |
| 177 EXPECT_EQ(HB_SCRIPT_HAN, script); | 179 EXPECT_EQ(HB_SCRIPT_HAN, script); |
| 178 | 180 |
| 179 ASSERT_TRUE( | 181 ASSERT_TRUE( |
| 180 testInfo(result)->runInfoForTesting(3, startIndex, numGlyphs, script)); | 182 testInfo(result)->runInfoForTesting(3, startIndex, numGlyphs, script)); |
| 181 EXPECT_EQ(5u, startIndex); | 183 EXPECT_EQ(5u, startIndex); |
| 182 EXPECT_EQ(1u, numGlyphs); | 184 EXPECT_EQ(1u, numGlyphs); |
| 183 EXPECT_EQ(HB_SCRIPT_LATIN, script); | 185 EXPECT_EQ(HB_SCRIPT_LATIN, script); |
| 184 } | 186 } |
| 185 | 187 |
| 186 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) { | 188 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) { |
| 187 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; | 189 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; |
| 188 HarfBuzzShaper shaper(mixedString, 6); | 190 HarfBuzzShaper shaper(mixedString, 6); |
| 189 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 191 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 190 ASSERT_EQ(4u, testInfo(result)->numberOfRunsForTesting()); | 192 EXPECT_EQ(4u, testInfo(result)->numberOfRunsForTesting()); |
| 191 | 193 |
| 192 // Shape again on the same shape object and check the number of runs. | 194 // Shape again on the same shape object and check the number of runs. |
| 193 // Should be equal if no state was retained between shape calls. | 195 // Should be equal if no state was retained between shape calls. |
| 194 RefPtr<ShapeResult> result2 = shaper.shape(&font, TextDirection::kLtr); | 196 RefPtr<ShapeResult> result2 = shaper.shape(&font, TextDirection::kLtr); |
| 195 ASSERT_EQ(4u, testInfo(result2)->numberOfRunsForTesting()); | 197 EXPECT_EQ(4u, testInfo(result2)->numberOfRunsForTesting()); |
| 196 } | 198 } |
| 197 | 199 |
| 198 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) { | 200 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) { |
| 199 UChar arabicString[] = {0x628, 0x64A, 0x629}; | 201 UChar arabicString[] = {0x628, 0x64A, 0x629}; |
| 200 HarfBuzzShaper shaper(arabicString, 3); | 202 HarfBuzzShaper shaper(arabicString, 3); |
| 201 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kRtl); | 203 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kRtl); |
| 202 | 204 |
| 203 ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); | 205 EXPECT_EQ(1u, testInfo(result)->numberOfRunsForTesting()); |
| 204 ASSERT_TRUE( | 206 ASSERT_TRUE( |
| 205 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); | 207 testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script)); |
| 206 EXPECT_EQ(0u, startIndex); | 208 EXPECT_EQ(0u, startIndex); |
| 207 EXPECT_EQ(3u, numGlyphs); | 209 EXPECT_EQ(3u, numGlyphs); |
| 208 EXPECT_EQ(HB_SCRIPT_ARABIC, script); | 210 EXPECT_EQ(HB_SCRIPT_ARABIC, script); |
| 209 } | 211 } |
| 210 | 212 |
| 211 // This is a simplified test and doesn't accuratly reflect how the shape range | 213 // This is a simplified test and doesn't accuratly reflect how the shape range |
| 212 // is to be used. If you instead of the string you imagine the following HTML: | 214 // is to be used. If you instead of the string you imagine the following HTML: |
| 213 // <div>Hello <span>World</span>!</div> | 215 // <div>Hello <span>World</span>!</div> |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 | 269 |
| 268 TEST_F(HarfBuzzShaperTest, PositionForOffsetLatin) { | 270 TEST_F(HarfBuzzShaperTest, PositionForOffsetLatin) { |
| 269 String string = to16Bit("Hello World!", 12); | 271 String string = to16Bit("Hello World!", 12); |
| 270 TextDirection direction = TextDirection::kLtr; | 272 TextDirection direction = TextDirection::kLtr; |
| 271 | 273 |
| 272 HarfBuzzShaper shaper(string.characters16(), 12); | 274 HarfBuzzShaper shaper(string.characters16(), 12); |
| 273 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | 275 RefPtr<ShapeResult> result = shaper.shape(&font, direction); |
| 274 RefPtr<ShapeResult> first = shaper.shape(&font, direction, 0, 5); // Hello | 276 RefPtr<ShapeResult> first = shaper.shape(&font, direction, 0, 5); // Hello |
| 275 RefPtr<ShapeResult> second = shaper.shape(&font, direction, 6, 11); // World | 277 RefPtr<ShapeResult> second = shaper.shape(&font, direction, 6, 11); // World |
| 276 | 278 |
| 277 ASSERT_EQ(0.0f, result->positionForOffset(0)); | 279 EXPECT_EQ(0.0f, result->positionForOffset(0)); |
| 278 ASSERT_NEAR(first->width(), result->positionForOffset(5), 1); | 280 ASSERT_NEAR(first->width(), result->positionForOffset(5), 1); |
| 279 ASSERT_NEAR(second->width(), | 281 ASSERT_NEAR(second->width(), |
| 280 result->positionForOffset(11) - result->positionForOffset(6), 1); | 282 result->positionForOffset(11) - result->positionForOffset(6), 1); |
| 281 ASSERT_NEAR(result->width(), result->positionForOffset(12), 0.1); | 283 ASSERT_NEAR(result->width(), result->positionForOffset(12), 0.1); |
| 282 } | 284 } |
| 283 | 285 |
| 284 TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) { | 286 TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) { |
| 285 UChar arabicString[] = {0x628, 0x64A, 0x629}; | 287 UChar arabicString[] = {0x628, 0x64A, 0x629}; |
| 286 TextDirection direction = TextDirection::kRtl; | 288 TextDirection direction = TextDirection::kRtl; |
| 287 | 289 |
| 288 HarfBuzzShaper shaper(arabicString, 3); | 290 HarfBuzzShaper shaper(arabicString, 3); |
| 289 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | 291 RefPtr<ShapeResult> result = shaper.shape(&font, direction); |
| 290 | 292 |
| 291 ASSERT_EQ(0.0f, result->positionForOffset(3)); | 293 EXPECT_EQ(0.0f, result->positionForOffset(3)); |
| 292 ASSERT_NEAR(result->width(), result->positionForOffset(0), 0.1); | 294 ASSERT_NEAR(result->width(), result->positionForOffset(0), 0.1); |
| 293 } | 295 } |
| 294 | 296 |
| 295 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetLatin) { | 297 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetLatin) { |
| 296 String string = to16Bit("Hello World!", 12); | 298 String string = to16Bit("Hello World!", 12); |
| 297 TextDirection direction = TextDirection::kLtr; | 299 TextDirection direction = TextDirection::kLtr; |
| 298 | 300 |
| 299 HarfBuzzShaper shaper(string.characters16(), 12); | 301 HarfBuzzShaper shaper(string.characters16(), 12); |
| 300 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | 302 RefPtr<ShapeResult> result = shaper.shape(&font, direction); |
| 301 | 303 |
| 302 // Last argument is includePartialGlyphs | 304 // Last argument is includePartialGlyphs |
| 303 ASSERT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); | 305 EXPECT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); |
| 304 ASSERT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); | 306 EXPECT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); |
| 305 ASSERT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); | 307 EXPECT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); |
| 306 ASSERT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); | 308 EXPECT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); |
| 307 ASSERT_EQ(4u, result->offsetForPosition(result->positionForOffset(4), true)); | 309 EXPECT_EQ(4u, result->offsetForPosition(result->positionForOffset(4), true)); |
| 308 ASSERT_EQ(5u, result->offsetForPosition(result->positionForOffset(5), true)); | 310 EXPECT_EQ(5u, result->offsetForPosition(result->positionForOffset(5), true)); |
| 309 ASSERT_EQ(6u, result->offsetForPosition(result->positionForOffset(6), true)); | 311 EXPECT_EQ(6u, result->offsetForPosition(result->positionForOffset(6), true)); |
| 310 ASSERT_EQ(7u, result->offsetForPosition(result->positionForOffset(7), true)); | 312 EXPECT_EQ(7u, result->offsetForPosition(result->positionForOffset(7), true)); |
| 311 ASSERT_EQ(8u, result->offsetForPosition(result->positionForOffset(8), true)); | 313 EXPECT_EQ(8u, result->offsetForPosition(result->positionForOffset(8), true)); |
| 312 ASSERT_EQ(9u, result->offsetForPosition(result->positionForOffset(9), true)); | 314 EXPECT_EQ(9u, result->offsetForPosition(result->positionForOffset(9), true)); |
| 313 ASSERT_EQ(10u, | 315 EXPECT_EQ(10u, |
| 314 result->offsetForPosition(result->positionForOffset(10), true)); | 316 result->offsetForPosition(result->positionForOffset(10), true)); |
| 315 ASSERT_EQ(11u, | 317 EXPECT_EQ(11u, |
| 316 result->offsetForPosition(result->positionForOffset(11), true)); | 318 result->offsetForPosition(result->positionForOffset(11), true)); |
| 317 ASSERT_EQ(12u, | 319 EXPECT_EQ(12u, |
| 318 result->offsetForPosition(result->positionForOffset(12), true)); | 320 result->offsetForPosition(result->positionForOffset(12), true)); |
| 319 } | 321 } |
| 320 | 322 |
| 321 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetArabic) { | 323 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetArabic) { |
| 322 UChar arabicString[] = {0x628, 0x64A, 0x629}; | 324 UChar arabicString[] = {0x628, 0x64A, 0x629}; |
| 323 TextDirection direction = TextDirection::kRtl; | 325 TextDirection direction = TextDirection::kRtl; |
| 324 | 326 |
| 325 HarfBuzzShaper shaper(arabicString, 3); | 327 HarfBuzzShaper shaper(arabicString, 3); |
| 326 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | 328 RefPtr<ShapeResult> result = shaper.shape(&font, direction); |
| 327 | 329 |
| 328 // Last argument is includePartialGlyphs | 330 // Last argument is includePartialGlyphs |
| 329 ASSERT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); | 331 EXPECT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); |
| 330 ASSERT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); | 332 EXPECT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); |
| 331 ASSERT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); | 333 EXPECT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); |
| 332 ASSERT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); | 334 EXPECT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); |
| 333 } | 335 } |
| 334 | 336 |
| 335 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetMixed) { | 337 TEST_F(HarfBuzzShaperTest, OffsetForPositionMatchesPositionForOffsetMixed) { |
| 336 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; | 338 UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62}; |
| 337 HarfBuzzShaper shaper(mixedString, 6); | 339 HarfBuzzShaper shaper(mixedString, 6); |
| 338 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); | 340 RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr); |
| 339 | 341 |
| 340 // Last argument is includePartialGlyphs | 342 // Last argument is includePartialGlyphs |
| 341 ASSERT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); | 343 EXPECT_EQ(0u, result->offsetForPosition(result->positionForOffset(0), true)); |
| 342 ASSERT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); | 344 EXPECT_EQ(1u, result->offsetForPosition(result->positionForOffset(1), true)); |
| 343 ASSERT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); | 345 EXPECT_EQ(2u, result->offsetForPosition(result->positionForOffset(2), true)); |
| 344 ASSERT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); | 346 EXPECT_EQ(3u, result->offsetForPosition(result->positionForOffset(3), true)); |
| 345 ASSERT_EQ(4u, result->offsetForPosition(result->positionForOffset(4), true)); | 347 EXPECT_EQ(4u, result->offsetForPosition(result->positionForOffset(4), true)); |
| 346 ASSERT_EQ(5u, result->offsetForPosition(result->positionForOffset(5), true)); | 348 EXPECT_EQ(5u, result->offsetForPosition(result->positionForOffset(5), true)); |
| 347 ASSERT_EQ(6u, result->offsetForPosition(result->positionForOffset(6), true)); | 349 EXPECT_EQ(6u, result->offsetForPosition(result->positionForOffset(6), true)); |
| 350 } | |
| 351 | |
| 352 TEST_F(HarfBuzzShaperTest, ShapeLineLatin) { | |
| 353 String string = to16Bit( | |
| 354 "Test run with multiple words and breaking " | |
| 355 "opportunities.", | |
| 356 56); | |
|
kojii
2017/03/22 16:15:29
nit: nowadays I think you can, unless you prefer t
| |
| 357 const AtomicString locale = "en-US"; | |
| 358 TextDirection direction = TextDirection::kLtr; | |
| 359 LineBreakType breakType = LineBreakType::Normal; | |
| 360 | |
| 361 HarfBuzzShaper shaper(string.characters16(), 56); | |
| 362 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 363 | |
| 364 // "Test run with multiple" | |
| 365 RefPtr<ShapeResult> first4 = shaper.shape(&font, direction, 0, 22); | |
| 366 ASSERT_LT(first4->snappedWidth(), result->snappedWidth()); | |
| 367 | |
| 368 // "Test run with" | |
| 369 RefPtr<ShapeResult> first3 = shaper.shape(&font, direction, 0, 13); | |
| 370 ASSERT_LT(first3->snappedWidth(), first4->snappedWidth()); | |
| 371 | |
| 372 // "Test run" | |
| 373 RefPtr<ShapeResult> first2 = shaper.shape(&font, direction, 0, 8); | |
| 374 ASSERT_LT(first2->snappedWidth(), first3->snappedWidth()); | |
| 375 | |
| 376 // "Test" | |
| 377 RefPtr<ShapeResult> first1 = shaper.shape(&font, direction, 0, 4); | |
| 378 ASSERT_LT(first1->snappedWidth(), first2->snappedWidth()); | |
| 379 | |
| 380 // Test the case where the entire string fits. | |
| 381 unsigned breakOffset = 0; | |
| 382 RefPtr<ShapeResult> line = | |
| 383 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 384 result->snappedWidth(), &breakOffset); | |
| 385 EXPECT_EQ(56u, breakOffset); // After the end of the string. | |
| 386 EXPECT_EQ(result->snappedWidth(), line->snappedWidth()); | |
| 387 | |
| 388 // Test cases where we break between words. | |
| 389 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 390 first4->snappedWidth(), &breakOffset); | |
| 391 EXPECT_EQ(22u, breakOffset); // Between "multiple" and " words" | |
| 392 EXPECT_EQ(first4->snappedWidth(), line->snappedWidth()); | |
| 393 | |
| 394 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 395 first4->snappedWidth() + 10, &breakOffset); | |
| 396 EXPECT_EQ(22u, breakOffset); // Between "multiple" and " words" | |
| 397 EXPECT_EQ(first4->snappedWidth(), line->snappedWidth()); | |
| 398 | |
| 399 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 400 first4->snappedWidth() - 1, &breakOffset); | |
| 401 EXPECT_EQ(13u, breakOffset); // Between "width" and "multiple" | |
| 402 EXPECT_EQ(first3->snappedWidth(), line->snappedWidth()); | |
| 403 | |
| 404 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 405 first3->snappedWidth(), &breakOffset); | |
| 406 EXPECT_EQ(13u, breakOffset); // Between "width" and "multiple" | |
| 407 EXPECT_EQ(first3->snappedWidth(), line->snappedWidth()); | |
| 408 | |
| 409 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 410 first3->snappedWidth() - 1, &breakOffset); | |
| 411 EXPECT_EQ(8u, breakOffset); // Between "run" and "width" | |
| 412 EXPECT_EQ(first2->snappedWidth(), line->snappedWidth()); | |
| 413 | |
| 414 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 415 first2->snappedWidth(), &breakOffset); | |
| 416 EXPECT_EQ(8u, breakOffset); // Between "run" and "width" | |
| 417 EXPECT_EQ(first2->snappedWidth(), line->snappedWidth()); | |
| 418 | |
| 419 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 420 first2->snappedWidth() - 1, &breakOffset); | |
| 421 EXPECT_EQ(4u, breakOffset); // Between "Test" and "run" | |
| 422 EXPECT_EQ(first1->snappedWidth(), line->snappedWidth()); | |
| 423 | |
| 424 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 425 first1->snappedWidth(), &breakOffset); | |
| 426 EXPECT_EQ(4u, breakOffset); // Between "Test" and "run" | |
| 427 EXPECT_EQ(first1->snappedWidth(), line->snappedWidth()); | |
| 428 | |
| 429 // Test the case where we cannot break earlier. | |
| 430 line = shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 431 first1->snappedWidth() - 1, &breakOffset); | |
| 432 EXPECT_EQ(4u, breakOffset); // Between "Test" and "run" | |
| 433 EXPECT_EQ(first1->snappedWidth(), line->snappedWidth()); | |
| 434 } | |
| 435 | |
| 436 TEST_F(HarfBuzzShaperTest, ShapeLineLatinMultiLine) { | |
| 437 String string = to16Bit("Line breaking test case.", 24); | |
| 438 const AtomicString locale = "en-US"; | |
| 439 TextDirection direction = TextDirection::kLtr; | |
| 440 LineBreakType breakType = LineBreakType::Normal; | |
| 441 | |
| 442 HarfBuzzShaper shaper(string.characters16(), 24); | |
| 443 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 444 RefPtr<ShapeResult> first = shaper.shape(&font, direction, 0, 4); | |
| 445 RefPtr<ShapeResult> midThird = shaper.shape(&font, direction, 0, 16); | |
| 446 | |
| 447 unsigned breakOffset = 0; | |
| 448 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 449 result->snappedWidth() - 1, &breakOffset); | |
| 450 EXPECT_EQ(18u, breakOffset); | |
| 451 | |
| 452 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 453 result->snappedWidth(), &breakOffset); | |
| 454 EXPECT_EQ(24u, breakOffset); | |
| 455 | |
| 456 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 457 first->snappedWidth(), &breakOffset); | |
| 458 EXPECT_EQ(4u, breakOffset); | |
| 459 | |
| 460 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 461 midThird->snappedWidth(), &breakOffset); | |
| 462 EXPECT_EQ(13u, breakOffset); | |
| 463 | |
| 464 shaper.shapeLine(&font, result.get(), 13u, locale, breakType, | |
| 465 midThird->snappedWidth(), &breakOffset); | |
| 466 EXPECT_EQ(24u, breakOffset); | |
| 467 } | |
| 468 | |
| 469 TEST_F(HarfBuzzShaperTest, ShapeLineLatinBreakAll) { | |
| 470 String string = to16Bit("Testing break type-break all.", 29); | |
| 471 const AtomicString locale = "en-US"; | |
| 472 TextDirection direction = TextDirection::kLtr; | |
| 473 LineBreakType breakType = LineBreakType::BreakAll; | |
| 474 | |
| 475 HarfBuzzShaper shaper(string.characters16(), 29); | |
| 476 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 477 RefPtr<ShapeResult> midpoint = shaper.shape(&font, direction, 0, 16); | |
| 478 | |
| 479 unsigned breakOffset = 0; | |
| 480 RefPtr<ShapeResult> line = | |
| 481 shaper.shapeLine(&font, result.get(), 0, locale, breakType, | |
| 482 midpoint->snappedWidth(), &breakOffset); | |
| 483 EXPECT_EQ(16u, breakOffset); | |
| 484 EXPECT_EQ(midpoint->snappedWidth(), line->snappedWidth()); | |
| 485 | |
| 486 shaper.shapeLine(&font, result.get(), 16, locale, breakType, | |
| 487 result->snappedWidth(), &breakOffset); | |
| 488 EXPECT_EQ(29u, breakOffset); | |
| 489 EXPECT_GE(midpoint->snappedWidth(), line->snappedWidth()); | |
| 490 } | |
| 491 | |
| 492 TEST_F(HarfBuzzShaperTest, ShapeLineArabicThaiHanLatinBreakAll) { | |
| 493 UChar mixedString[] = {0x628, 0x20, 0x64A, 0x629, 0x20, 0xE20, 0x65E5, 0x62}; | |
| 494 const AtomicString locale = "ar_AE"; | |
| 495 TextDirection direction = TextDirection::kRtl; | |
| 496 LineBreakType breakType = LineBreakType::BreakAll; | |
| 497 | |
| 498 HarfBuzzShaper shaper(mixedString, 8); | |
| 499 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 500 unsigned breakOffset = 0; | |
| 501 shaper.shapeLine(&font, result.get(), 3, locale, breakType, | |
| 502 result->snappedWidth() / LayoutUnit(2), &breakOffset); | |
| 503 } | |
| 504 | |
| 505 TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) { | |
| 506 String string = to16Bit("Testing ShapeResult::createSubRun", 33); | |
| 507 TextDirection direction = TextDirection::kLtr; | |
| 508 | |
| 509 HarfBuzzShaper shaper(string.characters16(), 33); | |
| 510 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 511 | |
| 512 RefPtr<ShapeResult> compositeResult = | |
| 513 ShapeResult::create(&font, 0, direction); | |
| 514 result->copyRange(0, 10, compositeResult.get()); | |
| 515 result->copyRange(10, 20, compositeResult.get()); | |
| 516 result->copyRange(20, 30, compositeResult.get()); | |
| 517 result->copyRange(30, 33, compositeResult.get()); | |
| 518 | |
| 519 EXPECT_EQ(result->numCharacters(), compositeResult->numCharacters()); | |
| 520 EXPECT_EQ(result->snappedWidth(), compositeResult->snappedWidth()); | |
| 521 EXPECT_EQ(result->snappedStartPositionForOffset(0), | |
| 522 compositeResult->snappedStartPositionForOffset(0)); | |
| 523 EXPECT_EQ(result->snappedStartPositionForOffset(15), | |
| 524 compositeResult->snappedStartPositionForOffset(15)); | |
| 525 EXPECT_EQ(result->snappedStartPositionForOffset(30), | |
| 526 compositeResult->snappedStartPositionForOffset(30)); | |
| 527 EXPECT_EQ(result->snappedStartPositionForOffset(33), | |
| 528 compositeResult->snappedStartPositionForOffset(33)); | |
| 529 } | |
| 530 | |
| 531 TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) { | |
| 532 UChar mixedString[] = {0x628, 0x20, 0x64A, 0x629, 0x20, 0xE20, 0x65E5, 0x62}; | |
| 533 TextDirection direction = TextDirection::kLtr; | |
| 534 | |
| 535 HarfBuzzShaper shaper(mixedString, 8); | |
| 536 RefPtr<ShapeResult> result = shaper.shape(&font, direction); | |
| 537 | |
| 538 RefPtr<ShapeResult> compositeResult = | |
| 539 ShapeResult::create(&font, 0, direction); | |
| 540 result->copyRange(0, 3, compositeResult.get()); | |
| 541 result->copyRange(3, 6, compositeResult.get()); | |
| 542 result->copyRange(6, 8, compositeResult.get()); | |
| 543 | |
| 544 EXPECT_EQ(result->numCharacters(), compositeResult->numCharacters()); | |
| 545 EXPECT_EQ(result->snappedWidth(), compositeResult->snappedWidth()); | |
| 546 EXPECT_EQ(result->snappedStartPositionForOffset(0), | |
| 547 compositeResult->snappedStartPositionForOffset(0)); | |
| 548 EXPECT_EQ(result->snappedStartPositionForOffset(1), | |
| 549 compositeResult->snappedStartPositionForOffset(1)); | |
| 550 EXPECT_EQ(result->snappedStartPositionForOffset(2), | |
| 551 compositeResult->snappedStartPositionForOffset(2)); | |
| 552 EXPECT_EQ(result->snappedStartPositionForOffset(3), | |
| 553 compositeResult->snappedStartPositionForOffset(3)); | |
| 554 EXPECT_EQ(result->snappedStartPositionForOffset(4), | |
| 555 compositeResult->snappedStartPositionForOffset(4)); | |
| 556 EXPECT_EQ(result->snappedStartPositionForOffset(5), | |
| 557 compositeResult->snappedStartPositionForOffset(5)); | |
| 558 EXPECT_EQ(result->snappedStartPositionForOffset(6), | |
| 559 compositeResult->snappedStartPositionForOffset(6)); | |
| 560 EXPECT_EQ(result->snappedStartPositionForOffset(7), | |
| 561 compositeResult->snappedStartPositionForOffset(7)); | |
| 562 EXPECT_EQ(result->snappedStartPositionForOffset(8), | |
| 563 compositeResult->snappedStartPositionForOffset(8)); | |
| 348 } | 564 } |
| 349 | 565 |
| 350 } // namespace blink | 566 } // namespace blink |
| OLD | NEW |