#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include <unicode/uscript.h>
#include "base/check.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
#include "third_party/blink/renderer/platform/fonts/font_test_utilities.h"
#include "third_party/blink/renderer/platform/fonts/font_variant_emoji.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/testing/font_test_base.h"
#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif
ElementsAre;
namespace blink {
namespace {
const ShapeResultTestInfo* TestInfo(const ShapeResult* result) { … }
struct ShapeResultRunData { … };
bool operator==(const ShapeResultRunData& x, const ShapeResultRunData& y) { … }
void operator<<(std::ostream& output, const ShapeResultRunData& x) { … }
String CreateStringOf(UChar ch, unsigned length) { … }
}
class HarfBuzzShaperTest : public FontTestBase { … };
class ScopedSubpixelOverride { … };
class ShapeParameterTest : public HarfBuzzShaperTest,
public testing::WithParamInterface<TextDirection> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) { … }
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) { … }
TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) { … }
#if BUILDFLAG(IS_APPLE)
#define MAYBE_ShapeArabicWithContext …
#else
#define MAYBE_ShapeArabicWithContext …
#endif
TEST_F(HarfBuzzShaperTest, MAYBE_ShapeArabicWithContext) { … }
TEST_F(HarfBuzzShaperTest, ShapeTabulationCharacters) { … }
TEST_F(HarfBuzzShaperTest, ShapeVerticalUpright) { … }
TEST_F(HarfBuzzShaperTest, ShapeVerticalUprightIdeograph) { … }
TEST_F(HarfBuzzShaperTest, RangeShapeSmallCaps) { … }
TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) { … }
class ShapeStringTest : public HarfBuzzShaperTest,
public testing::WithParamInterface<const char16_t*> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(ShapeStringTest, MissingGlyph) { … }
TEST_P(ShapeParameterTest, MaxGlyphsSimple) { … }
TEST_P(ShapeParameterTest, MaxGlyphsClusterLatin) { … }
TEST_P(ShapeParameterTest, MaxGlyphsClusterLatin2) { … }
TEST_P(ShapeParameterTest, MaxGlyphsClusterDevanagari) { … }
TEST_P(ShapeParameterTest, ZeroWidthSpace) { … }
TEST_F(HarfBuzzShaperTest, IdeographicSpace) { … }
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
TEST_F(HarfBuzzShaperTest, SystemEmojiVS15) {
ScopedFontVariationSequencesForTest scoped_feature_vs(true);
ScopedSystemFallbackEmojiVSSupportForTest scoped_feature_system_emoji_vs(
true);
Font mono_font = CreateNotoEmoji();
Font color_font = CreateNotoColorEmoji();
String text_default(
u"\u2603"
u"\ufe0e");
String emoji_default(
u"\u2614"
u"\ufe0e");
for (String text : {text_default, emoji_default}) {
EXPECT_EQ(GetShapedFontFamilyNameForEmojiVS(mono_font, text),
kNotoEmojiFontName);
EXPECT_EQ(GetShapedFontFamilyNameForEmojiVS(color_font, text),
kSystemMonoEmojiFont);
}
}
TEST_F(HarfBuzzShaperTest, SystemEmojiVS16) {
ScopedFontVariationSequencesForTest scoped_feature_vs(true);
ScopedSystemFallbackEmojiVSSupportForTest scoped_feature_system_emoji_vs(
true);
Font mono_font = CreateNotoEmoji();
Font color_font = CreateNotoColorEmoji();
String text_default(
u"\u2603"
u"\ufe0f");
String emoji_default(
u"\u2614"
u"\ufe0f");
for (String text : {text_default, emoji_default}) {
EXPECT_EQ(GetShapedFontFamilyNameForEmojiVS(mono_font, text),
kSystemColorEmojiFont);
EXPECT_EQ(GetShapedFontFamilyNameForEmojiVS(color_font, text),
kNotoColorEmojiFontName);
}
}
#endif
TEST_F(HarfBuzzShaperTest, NegativeLetterSpacing) { … }
TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingTo0) { … }
TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingToNegative) { … }
static struct GlyphDataRangeTestData { … } glyph_data_range_test_data[] = …;
std::ostream& operator<<(std::ostream& ostream,
const GlyphDataRangeTestData& data) { … }
class GlyphDataRangeTest
: public HarfBuzzShaperTest,
public testing::WithParamInterface<GlyphDataRangeTestData> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(GlyphDataRangeTest, Data) { … }
static struct OffsetForPositionTestData { … } offset_for_position_fixed_pitch_test_data[] = …;
std::ostream& operator<<(std::ostream& ostream,
const OffsetForPositionTestData& data) { … }
class OffsetForPositionTest
: public HarfBuzzShaperTest,
public testing::WithParamInterface<OffsetForPositionTestData> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(OffsetForPositionTest, Data) { … }
TEST_F(HarfBuzzShaperTest, PositionForOffsetLatin) { … }
TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) { … }
TEST_F(HarfBuzzShaperTest, EmojiZWJSequence) { … }
class IncludePartialGlyphsTest
: public HarfBuzzShaperTest,
public ::testing::WithParamInterface<IncludePartialGlyphsOption> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(IncludePartialGlyphsTest,
OffsetForPositionMatchesPositionForOffsetLatin) { … }
TEST_P(IncludePartialGlyphsTest,
OffsetForPositionMatchesPositionForOffsetArabic) { … }
TEST_P(IncludePartialGlyphsTest,
OffsetForPositionMatchesPositionForOffsetMixed) { … }
TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingForOffsetLatin) { … }
TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingArabic) { … }
TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingMixed) { … }
TEST_F(HarfBuzzShaperTest, PositionForOffsetMultiGlyphClusterLtr) { … }
TEST_F(HarfBuzzShaperTest, PositionForOffsetMultiGlyphClusterRtl) { … }
TEST_F(HarfBuzzShaperTest, PositionForOffsetMissingGlyph) { … }
static struct ShapeResultCopyRangeTestData { … } shape_result_copy_range_test_data[] = …;
std::ostream& operator<<(std::ostream& ostream,
const ShapeResultCopyRangeTestData& data) { … }
class ShapeResultCopyRangeTest
: public HarfBuzzShaperTest,
public testing::WithParamInterface<ShapeResultCopyRangeTestData> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(ShapeResultCopyRangeTest, Split) { … }
TEST_P(ShapeResultCopyRangeTest, ShapeRange) { … }
TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) { … }
TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) { … }
TEST_P(ShapeParameterTest, ShapeResultCopyRangeAcrossRuns) { … }
TEST_P(ShapeParameterTest, ShapeResultCopyRangeContextMultiRuns) { … }
TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeSegmentGlyphBoundingBox) { … }
TEST_F(HarfBuzzShaperTest, SubRange) { … }
TEST_F(HarfBuzzShaperTest, SafeToBreakLatinCommonLigatures) { … }
TEST_F(HarfBuzzShaperTest, SafeToBreakPreviousLatinCommonLigatures) { … }
TEST_F(HarfBuzzShaperTest, SafeToBreakLatinDiscretionaryLigatures) { … }
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
#define MAYBE_SafeToBreakArabicCommonLigatures …
#else
#define MAYBE_SafeToBreakArabicCommonLigatures …
#endif
TEST_F(HarfBuzzShaperTest, MAYBE_SafeToBreakArabicCommonLigatures) { … }
TEST_F(HarfBuzzShaperTest, SafeToBreakU0635) { … }
TEST_P(ShapeParameterTest, SafeToBreakMissingRun) { … }
TEST_P(ShapeParameterTest, CopyRangeMissingRun) { … }
TEST_P(ShapeParameterTest, CopyRangeNoRuns) { … }
TEST_P(ShapeParameterTest, ShapeResultViewMissingRun) { … }
static bool KerningIsHappening(const FontDescription& font_description,
TextDirection direction,
const String& str) { … }
TEST_F(HarfBuzzShaperTest, KerningIsHappeningWorks) { … }
TEST_F(HarfBuzzShaperTest,
ShapeHorizontalWithoutSubpixelPositionWithoutKerningIsRounded) { … }
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded …
#else
#define MAYBE_ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded …
#endif
TEST_F(HarfBuzzShaperTest,
MAYBE_ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded) { … }
TEST_F(HarfBuzzShaperTest,
ShapeHorizontalWithoutSubpixelPositionWithKerningIsRounded) { … }
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_ShapeHorizontalWithSubpixelPositionWithKerningIsNotRounded …
#else
#define MAYBE_ShapeHorizontalWithSubpixelPositionWithKerningIsNotRounded …
#endif
TEST_F(HarfBuzzShaperTest,
MAYBE_ShapeHorizontalWithSubpixelPositionWithKerningIsNotRounded) { … }
TEST_F(HarfBuzzShaperTest, ShapeVerticalWithoutSubpixelPositionIsRounded) { … }
TEST_F(HarfBuzzShaperTest, ShapeVerticalWithSubpixelPositionIsRounded) { … }
#if BUILDFLAG(IS_APPLE)
#define MAYBE_EmojiPercentage …
#else
#define MAYBE_EmojiPercentage …
#endif
TEST_F(HarfBuzzShaperTest, MAYBE_EmojiPercentage) { … }
TEST_F(HarfBuzzShaperTest, OverlyLongGraphemeCluster) { … }
TEST_F(HarfBuzzShaperTest, UnorderedClusterIndex) { … }
}