summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/fonts/shaping/font_features_test.cc
blob: 61205474ddfd5eeeb7180f95bf91b70ce61b4f59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/fonts/shaping/font_features.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"

namespace blink {

namespace {

class FontFeaturesTest : public testing::Test {};

static const FontOrientation orientations[] = {
    FontOrientation::kHorizontal,
    FontOrientation::kVerticalRotated,
    FontOrientation::kVerticalMixed,
    FontOrientation::kVerticalUpright,
};

class FontFeaturesByOrientationTest
    : public FontFeaturesTest,
      public testing::WithParamInterface<FontOrientation> {
 public:
  FontOrientation GetOrientation() const { return GetParam(); }
  bool IsHorizontal() const { return !IsVerticalAnyUpright(GetOrientation()); }
};

INSTANTIATE_TEST_SUITE_P(FontFeaturesTest,
                         FontFeaturesByOrientationTest,
                         testing::ValuesIn(orientations));

// Test 'chws' or 'vchw' is on by default.
TEST_P(FontFeaturesByOrientationTest, EastAsianContextualSpacingOnByDefault) {
  constexpr hb_tag_t chws = HB_TAG('c', 'h', 'w', 's');
  constexpr hb_tag_t vchw = HB_TAG('v', 'c', 'h', 'w');
  FontDescription font_description;
  font_description.SetOrientation(GetOrientation());
  FontFeatures features;
  features.Initialize(font_description);
  if (IsHorizontal()) {
    EXPECT_EQ(features.FindValueForTesting(chws), 1u);
    EXPECT_EQ(features.FindValueForTesting(vchw), absl::nullopt);
  } else {
    EXPECT_EQ(features.FindValueForTesting(chws), absl::nullopt);
    EXPECT_EQ(features.FindValueForTesting(vchw), 1u);
  }
}

// If author opted-in or opted-out, it should be honored.
TEST_P(FontFeaturesByOrientationTest,
       EastAsianContextualSpacingHonorsFontFeatureSettings) {
  constexpr hb_tag_t chws = HB_TAG('c', 'h', 'w', 's');
  constexpr hb_tag_t vchw = HB_TAG('v', 'c', 'h', 'w');
  for (unsigned value = 0; value <= 1; ++value) {
    scoped_refptr<FontFeatureSettings> settings = FontFeatureSettings::Create();
    settings->Append({IsHorizontal() ? chws : vchw, static_cast<int>(value)});
    FontDescription font_description;
    font_description.SetOrientation(GetOrientation());
    font_description.SetFeatureSettings(settings);
    FontFeatures features;
    features.Initialize(font_description);
    if (IsHorizontal()) {
      EXPECT_EQ(features.FindValueForTesting(chws), value);
      EXPECT_EQ(features.FindValueForTesting(vchw), absl::nullopt);
    } else {
      EXPECT_EQ(features.FindValueForTesting(chws), absl::nullopt);
      EXPECT_EQ(features.FindValueForTesting(vchw), value);
    }
  }
}

// Test glyph-width GPOS features that should not enable 'chws'/'vchw'.
TEST_P(FontFeaturesByOrientationTest,
       EastAsianContextualSpacingOffByFeatureSettings) {
  constexpr hb_tag_t chws = HB_TAG('c', 'h', 'w', 's');
  constexpr hb_tag_t vchw = HB_TAG('v', 'c', 'h', 'w');
  const hb_tag_t tags[] = {
      IsHorizontal() ? HB_TAG('h', 'a', 'l', 't') : HB_TAG('v', 'h', 'a', 'l'),
      IsHorizontal() ? HB_TAG('p', 'a', 'l', 't') : HB_TAG('v', 'p', 'a', 'l'),
  };
  for (const hb_tag_t tag : tags) {
    scoped_refptr<FontFeatureSettings> settings = FontFeatureSettings::Create();
    settings->Append({tag, 1});
    FontDescription font_description;
    font_description.SetOrientation(GetOrientation());
    font_description.SetFeatureSettings(settings);
    FontFeatures features;
    features.Initialize(font_description);
    EXPECT_EQ(features.FindValueForTesting(chws), absl::nullopt);
    EXPECT_EQ(features.FindValueForTesting(vchw), absl::nullopt);
  }
}

// Test the current behavior when multiple glyph-width GPOS features are set via
// `FontFeatureSettings`. Current |FontFeatures| does not resolve conflicts,
// just pass them all as specified to HarfBuzz.
TEST_P(FontFeaturesByOrientationTest, MultipleGlyphWidthGPOS) {
  const hb_tag_t tags[] = {
      HB_TAG('c', 'h', 'w', 's'), HB_TAG('v', 'c', 'h', 'w'),
      HB_TAG('h', 'a', 'l', 't'), HB_TAG('v', 'h', 'a', 'l'),
      HB_TAG('p', 'a', 'l', 't'), HB_TAG('v', 'p', 'a', 'l'),
  };
  scoped_refptr<FontFeatureSettings> settings = FontFeatureSettings::Create();
  for (const hb_tag_t tag : tags)
    settings->Append({tag, 1});
  FontDescription font_description;
  font_description.SetOrientation(GetOrientation());
  font_description.SetFeatureSettings(settings);
  FontFeatures features;
  features.Initialize(font_description);
  // Check all features are enabled.
  for (const hb_tag_t tag : tags)
    EXPECT_EQ(features.FindValueForTesting(tag), 1u);
}

}  // namespace

}  // namespace blink