1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <test/bootstrapfixture.hxx>
11 #include <config_features.h>
12 #include <cppunit/TestAssert.h>
14 #include <vcl/font/Feature.hxx>
15 #include <vcl/font/FeatureParser.hxx>
16 #include <vcl/virdev.hxx>
17 #include <vcl/svapp.hxx>
19 class FontFeatureTest
: public test::BootstrapFixture
23 : BootstrapFixture(true, false)
27 void testGetFontFeatures();
28 void testParseFeature();
30 CPPUNIT_TEST_SUITE(FontFeatureTest
);
31 CPPUNIT_TEST(testGetFontFeatures
);
32 CPPUNIT_TEST(testParseFeature
);
33 CPPUNIT_TEST_SUITE_END();
36 void FontFeatureTest::testGetFontFeatures()
39 ScopedVclPtrInstance
<VirtualDevice
> aVDev(*Application::GetDefaultDevice(),
40 DeviceFormat::DEFAULT
, DeviceFormat::DEFAULT
);
41 aVDev
->SetOutputSizePixel(Size(10, 10));
43 OUString
aFontName("Linux Libertine G");
44 CPPUNIT_ASSERT(aVDev
->IsFontAvailable(aFontName
));
46 vcl::Font aFont
= aVDev
->GetFont();
47 aFont
.SetFamilyName(aFontName
);
48 aFont
.SetWeight(FontWeight::WEIGHT_NORMAL
);
49 aFont
.SetItalic(FontItalic::ITALIC_NORMAL
);
50 aFont
.SetWidthType(FontWidth::WIDTH_NORMAL
);
51 aVDev
->SetFont(aFont
);
53 std::vector
<vcl::font::Feature
> rFontFeatures
;
54 CPPUNIT_ASSERT(aVDev
->GetFontFeatures(rFontFeatures
));
56 // We're interested only in defaults here
57 std::vector
<vcl::font::Feature
> rDefaultFontFeatures
;
58 OUString aFeaturesString
;
59 for (vcl::font::Feature
const& rFeature
: rFontFeatures
)
61 if (rFeature
.m_aID
.m_aScriptCode
== vcl::font::featureCode("DFLT")
62 && rFeature
.m_aID
.m_aLanguageCode
== vcl::font::featureCode("dflt"))
64 rDefaultFontFeatures
.push_back(rFeature
);
65 aFeaturesString
+= vcl::font::featureCodeAsString(rFeature
.m_aID
.m_aFeatureCode
) + " ";
69 CPPUNIT_ASSERT_EQUAL(size_t(53), rDefaultFontFeatures
.size());
71 CPPUNIT_ASSERT_EQUAL(OUString("c2sc case dlig fina frac hlig liga lnum "
72 "locl onum pnum sa01 sa02 sa03 sa04 sa05 "
73 "sa06 sa07 sa08 salt sinf smcp ss01 ss02 "
74 "ss03 sups tnum zero ingl cpsp lith litt "
75 "itlc para algn arti circ dash dbls foot "
76 "frsp grkn hang lng minu nfsp name quot "
77 "texm thou vari caps ligc "),
82 vcl::font::Feature
& rFeature
= rDefaultFontFeatures
[0];
83 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("c2sc"), rFeature
.m_aID
.m_aFeatureCode
);
85 vcl::font::FeatureDefinition
& rFracFeatureDefinition
= rFeature
.m_aDefinition
;
86 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("c2sc"), rFracFeatureDefinition
.getCode());
87 CPPUNIT_ASSERT(!rFracFeatureDefinition
.getDescription().isEmpty());
88 CPPUNIT_ASSERT_EQUAL(vcl::font::FeatureParameterType::BOOL
,
89 rFracFeatureDefinition
.getType());
91 CPPUNIT_ASSERT_EQUAL(size_t(0), rFracFeatureDefinition
.getEnumParameters().size());
96 vcl::font::Feature
& rFeature
= rDefaultFontFeatures
[4];
97 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("frac"), rFeature
.m_aID
.m_aFeatureCode
);
99 vcl::font::FeatureDefinition
& rFracFeatureDefinition
= rFeature
.m_aDefinition
;
100 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("frac"), rFracFeatureDefinition
.getCode());
101 CPPUNIT_ASSERT(!rFracFeatureDefinition
.getDescription().isEmpty());
102 CPPUNIT_ASSERT_EQUAL(vcl::font::FeatureParameterType::ENUM
,
103 rFracFeatureDefinition
.getType());
105 CPPUNIT_ASSERT_EQUAL(size_t(3), rFracFeatureDefinition
.getEnumParameters().size());
107 vcl::font::FeatureParameter
const& rParameter1
108 = rFracFeatureDefinition
.getEnumParameters()[0];
109 CPPUNIT_ASSERT_EQUAL(uint32_t(0), rParameter1
.getCode());
110 CPPUNIT_ASSERT(!rParameter1
.getDescription().isEmpty());
112 vcl::font::FeatureParameter
const& rParameter2
113 = rFracFeatureDefinition
.getEnumParameters()[1];
114 CPPUNIT_ASSERT_EQUAL(uint32_t(1), rParameter2
.getCode());
115 CPPUNIT_ASSERT(!rParameter2
.getDescription().isEmpty());
117 vcl::font::FeatureParameter
const& rParameter3
118 = rFracFeatureDefinition
.getEnumParameters()[2];
119 CPPUNIT_ASSERT_EQUAL(uint32_t(2), rParameter3
.getCode());
120 CPPUNIT_ASSERT(!rParameter2
.getDescription().isEmpty());
123 aVDev
.disposeAndClear();
124 #endif // HAVE_MORE_FONTS
127 void FontFeatureTest::testParseFeature()
129 { // No font features specified
130 vcl::font::FeatureParser
aParser("Font name with no features");
131 CPPUNIT_ASSERT_EQUAL(size_t(0), aParser
.getFeatures().size());
133 { // One feature specified, no value
134 vcl::font::FeatureParser
aParser("Font name:abcd");
135 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
136 auto aFeatures
= aParser
.getFeatures();
138 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
139 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
141 { // One feature specified, explicit value
142 vcl::font::FeatureParser
aParser("Font name:abcd=5");
143 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
144 auto aFeatures
= aParser
.getFeatures();
146 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
147 CPPUNIT_ASSERT_EQUAL(uint32_t(5), aFeatures
[0].m_nValue
);
149 { // One feature specified, explicit zero value
150 vcl::font::FeatureParser
aParser("Font name:abcd=0");
151 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
152 auto aFeatures
= aParser
.getFeatures();
154 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
155 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[0].m_nValue
);
157 { // One feature specified, using plus prefix
158 vcl::font::FeatureParser
aParser("Font name:+abcd");
159 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
160 auto aFeatures
= aParser
.getFeatures();
162 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
163 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
165 { // One feature specified, using minus prefix
166 vcl::font::FeatureParser
aParser("Font name:-abcd");
167 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
168 auto aFeatures
= aParser
.getFeatures();
170 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
171 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[0].m_nValue
);
173 { // One feature specified, with empty character range
174 vcl::font::FeatureParser
aParser("Font name:abcd[]");
175 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
176 auto aFeatures
= aParser
.getFeatures();
178 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
179 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
180 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures
[0].m_nStart
);
181 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures
[0].m_nEnd
);
183 { // One feature specified, with empty character range
184 vcl::font::FeatureParser
aParser("Font name:abcd[:]");
185 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
186 auto aFeatures
= aParser
.getFeatures();
188 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
189 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
190 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures
[0].m_nStart
);
191 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures
[0].m_nEnd
);
193 { // One feature specified, with start character range
194 vcl::font::FeatureParser
aParser("Font name:abcd[3:]");
195 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
196 auto aFeatures
= aParser
.getFeatures();
198 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
199 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
200 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
201 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures
[0].m_nEnd
);
203 { // One feature specified, with end character range
204 vcl::font::FeatureParser
aParser("Font name:abcd[:3]");
205 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
206 auto aFeatures
= aParser
.getFeatures();
208 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
209 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
210 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures
[0].m_nStart
);
211 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nEnd
);
213 { // One feature specified, with character range
214 vcl::font::FeatureParser
aParser("Font name:abcd[3:6]");
215 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
216 auto aFeatures
= aParser
.getFeatures();
218 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
219 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
220 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
221 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures
[0].m_nEnd
);
223 { // One feature specified, with character range
224 vcl::font::FeatureParser
aParser("Font name:abcd[3]");
225 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
226 auto aFeatures
= aParser
.getFeatures();
228 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
229 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
230 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
231 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(4), aFeatures
[0].m_nEnd
);
233 { // One feature specified, with character range and value
234 vcl::font::FeatureParser
aParser("Font name:abcd[3:6]=2");
235 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
236 auto aFeatures
= aParser
.getFeatures();
238 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
239 CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures
[0].m_nValue
);
240 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
241 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures
[0].m_nEnd
);
243 { // One feature specified, with character range and 0 value
244 vcl::font::FeatureParser
aParser("Font name:abcd[3:6]=0");
245 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
246 auto aFeatures
= aParser
.getFeatures();
248 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
249 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[0].m_nValue
);
250 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
251 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures
[0].m_nEnd
);
253 { // One feature specified, with character range and minus prefix
254 vcl::font::FeatureParser
aParser("Font name:-abcd[3:6]");
255 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
256 auto aFeatures
= aParser
.getFeatures();
258 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
259 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[0].m_nValue
);
260 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures
[0].m_nStart
);
261 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures
[0].m_nEnd
);
263 { // One feature specified, with CSS on
264 vcl::font::FeatureParser
aParser("Font name:\"abcd\" on");
265 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
266 auto aFeatures
= aParser
.getFeatures();
268 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
269 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
271 { // One feature specified, with CSS off
272 vcl::font::FeatureParser
aParser("Font name:'abcd' off");
273 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
274 auto aFeatures
= aParser
.getFeatures();
276 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
277 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[0].m_nValue
);
279 { // One feature specified, with CSS value
280 vcl::font::FeatureParser
aParser("Font name:\"abcd\" 2");
281 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
282 auto aFeatures
= aParser
.getFeatures();
284 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
285 CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures
[0].m_nValue
);
287 { // Multiple features specified, no values
288 vcl::font::FeatureParser
aParser("Font name:abcd&bcde&efgh");
289 CPPUNIT_ASSERT_EQUAL(size_t(3), aParser
.getFeatures().size());
290 auto aFeatures
= aParser
.getFeatures();
292 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
293 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
295 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures
[1].m_nTag
);
296 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[1].m_nValue
);
298 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("efgh"), aFeatures
[2].m_nTag
);
299 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[2].m_nValue
);
302 // Multiple features specified, explicit values
303 // Only 4 char parameter names supported - "toolong" is too long and ignored
304 vcl::font::FeatureParser
aParser("Font name:abcd=1&bcde=0&toolong=1&cdef=3");
305 CPPUNIT_ASSERT_EQUAL(size_t(3), aParser
.getFeatures().size());
306 auto aFeatures
= aParser
.getFeatures();
308 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
309 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
311 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures
[1].m_nTag
);
312 CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures
[1].m_nValue
);
314 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("cdef"), aFeatures
[2].m_nTag
);
315 CPPUNIT_ASSERT_EQUAL(uint32_t(3), aFeatures
[2].m_nValue
);
318 // Special case - "lang" is parsed specially and access separately not as a feature.
320 vcl::font::FeatureParser
aParser("Font name:abcd=1&lang=slo");
321 CPPUNIT_ASSERT_EQUAL(size_t(1), aParser
.getFeatures().size());
322 auto aFeatures
= aParser
.getFeatures();
324 CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures
[0].m_nTag
);
325 CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures
[0].m_nValue
);
327 CPPUNIT_ASSERT_EQUAL(OUString("slo"), aParser
.getLanguage());
331 CPPUNIT_TEST_SUITE_REGISTRATION(FontFeatureTest
);
333 CPPUNIT_PLUGIN_IMPLEMENT();
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */