diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2018-06-15 19:32:15 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2018-06-16 18:04:31 +0200 |
commit | dc9ee533dc707cc10b99d537eaccc3ee5aa555fe (patch) | |
tree | bbe8c7547aac7b0440f874ed39945faa60a84276 | |
parent | 099eef24da24d638fdf2c747d28040c9b3a30780 (diff) |
vcl: parser of font features included in the font name
Change-Id: I7347410b4eb5e940d94c34aac4fdf344869541fa
Reviewed-on: https://gerrit.libreoffice.org/55893
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/vcl/font/FeatureParser.hxx | 52 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/qa/cppunit/FontFeatureTest.cxx | 69 | ||||
-rw-r--r-- | vcl/source/font/FeatureParser.cxx | 74 | ||||
-rw-r--r-- | vcl/source/gdi/CommonSalLayout.cxx | 27 |
5 files changed, 204 insertions, 19 deletions
diff --git a/include/vcl/font/FeatureParser.hxx b/include/vcl/font/FeatureParser.hxx new file mode 100644 index 000000000000..595bb0354b79 --- /dev/null +++ b/include/vcl/font/FeatureParser.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_VCL_FONT_FEATUREPASER_HXX +#define INCLUDED_VCL_FONT_FEATUREPASER_HXX + +#include <vcl/dllapi.h> +#include <rtl/ustring.hxx> +#include <rtl/string.hxx> +#include <memory> +#include <vector> +#include <unordered_map> +#include <vcl/font/Feature.hxx> + +namespace vcl +{ +namespace font +{ +// These must not conflict with font name lists which use ; and , +constexpr const char FeaturePrefix = ':'; +constexpr const char FeatureSeparator = '&'; + +VCL_DLLPUBLIC OUString trimFontNameFeatures(OUString const& rFontName); + +class VCL_DLLPUBLIC FeatureParser +{ +private: + OUString m_sLanguage; + std::vector<std::pair<sal_uInt32, sal_uInt32>> m_aFeatures; + +public: + FeatureParser(OUString const& sFontName); + + OUString getLanguage() const { return m_sLanguage; } + + std::vector<std::pair<sal_uInt32, sal_uInt32>> getFeatures() const { return m_aFeatures; } + + std::unordered_map<sal_uInt32, sal_uInt32> getFeaturesMap(); +}; + +} // end font namespace +} // end vcl namespace + +#endif // INCLUDED_VCL_FONT_FEATUREPASER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 58fbfaaa8b56..f01302fd1080 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -405,6 +405,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/filter/wmf/wmfwr \ vcl/source/font/Feature \ vcl/source/font/FeatureCollector \ + vcl/source/font/FeatureParser \ vcl/source/font/OpenTypeFeatureDefinitonList \ vcl/source/font/PhysicalFontCollection \ vcl/source/font/PhysicalFontFace \ diff --git a/vcl/qa/cppunit/FontFeatureTest.cxx b/vcl/qa/cppunit/FontFeatureTest.cxx index 0bb28e306139..63cc4913bb8d 100644 --- a/vcl/qa/cppunit/FontFeatureTest.cxx +++ b/vcl/qa/cppunit/FontFeatureTest.cxx @@ -10,8 +10,9 @@ #include <test/bootstrapfixture.hxx> #include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> -#include <vcl/font/Feature.hxx> +#include <vcl/font/Feature.hxx> +#include <vcl/font/FeatureParser.hxx> #include <vcl/virdev.hxx> #include <vcl/svapp.hxx> @@ -24,9 +25,11 @@ public: } void testGetFontFeatures(); + void testParseFeature(); CPPUNIT_TEST_SUITE(FontFeatureTest); CPPUNIT_TEST(testGetFontFeatures); + CPPUNIT_TEST(testParseFeature); CPPUNIT_TEST_SUITE_END(); }; @@ -103,6 +106,70 @@ void FontFeatureTest::testGetFontFeatures() } } +void FontFeatureTest::testParseFeature() +{ + { // No font features specified + vcl::font::FeatureParser aParser("Font name with no features"); + CPPUNIT_ASSERT_EQUAL(size_t(0), aParser.getFeatures().size()); + } + { // One feature specified, no value + vcl::font::FeatureParser aParser("Font name:abcd"); + CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size()); + auto aFeatures = aParser.getFeatures(); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[0].second); + } + { // One feature specified, explicit value + vcl::font::FeatureParser aParser("Font name:abcd=5"); + CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size()); + auto aFeatures = aParser.getFeatures(); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(5), aFeatures[0].second); + } + { // Multiple features specified, no values + vcl::font::FeatureParser aParser("Font name:abcd&bcde&efgh"); + CPPUNIT_ASSERT_EQUAL(size_t(3), aParser.getFeatures().size()); + auto aFeatures = aParser.getFeatures(); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[0].second); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures[1].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[1].second); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("efgh"), aFeatures[2].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[2].second); + } + { + // Multiple features specified, explicit values + // Only 4 char parameter names supported - "toolong" is too long and igoned + // If value is 0, it should be also ignored + vcl::font::FeatureParser aParser("Font name:abcd=1&bcde=0&toolong=1&cdef=3"); + CPPUNIT_ASSERT_EQUAL(size_t(2), aParser.getFeatures().size()); + auto aFeatures = aParser.getFeatures(); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[0].second); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("cdef"), aFeatures[1].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(3), aFeatures[1].second); + } + { + // Special case - "lang" is parsed specially and access separately not as a feature. + + vcl::font::FeatureParser aParser("Font name:abcd=1&lang=slo"); + CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size()); + auto aFeatures = aParser.getFeatures(); + + CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].first); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[0].second); + + CPPUNIT_ASSERT_EQUAL(OUString("slo"), aParser.getLanguage()); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(FontFeatureTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/vcl/source/font/FeatureParser.cxx b/vcl/source/font/FeatureParser.cxx new file mode 100644 index 000000000000..d61c0a89cfd6 --- /dev/null +++ b/vcl/source/font/FeatureParser.cxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <vcl/font/FeatureParser.hxx> + +namespace vcl +{ +namespace font +{ +OUString trimFontNameFeatures(OUString const& rFontName) +{ + OUString sResultName(rFontName); + + if (sResultName.indexOf(vcl::font::FeaturePrefix) < 0) + return sResultName; + + return sResultName.getToken(0, vcl::font::FeaturePrefix); +} + +FeatureParser::FeatureParser(OUString const& rFontName) +{ + if (rFontName.indexOf(vcl::font::FeaturePrefix) < 0) + return; + + OUString sName = rFontName.getToken(1, vcl::font::FeaturePrefix); + sal_Int32 nIndex = 0; + do + { + OUString sToken = sName.getToken(0, vcl::font::FeatureSeparator, nIndex); + + OUString sID = sToken.getToken(0, '='); + OUString sValue = sToken.getToken(1, '='); + + if (sID.getLength() == 4 && sValue != "0") + { + if (sID == "lang") + { + m_sLanguage = sValue; + } + else + { + OString sFeatureCodeAscii = OUStringToOString(sID, RTL_TEXTENCODING_ASCII_US); + sal_uInt32 nCode = vcl::font::featureCode(sFeatureCodeAscii.getStr()); + sal_uInt32 nValue = sValue.isEmpty() ? 1 : sValue.toUInt32(); + + if (nValue != 0) + m_aFeatures.emplace_back(nCode, nValue); + } + } + } while (nIndex >= 0); +} + +std::unordered_map<sal_uInt32, sal_uInt32> FeatureParser::getFeaturesMap() +{ + std::unordered_map<sal_uInt32, sal_uInt32> aResultMap; + for (auto const& rPair : m_aFeatures) + { + aResultMap.emplace(rPair); + } + return aResultMap; +} + +} // end font namespace + +} // end vcl namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 2eff9d96573a..eb3260bdbdc9 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -25,6 +25,8 @@ #include <unotools/configmgr.hxx> #include <vcl/unohelp.hxx> +#include <vcl/font/Feature.hxx> +#include <vcl/font/FeatureParser.hxx> #include <scrptrun.h> #include <com/sun/star/i18n/CharacterIteratorMode.hpp> #include <i18nlangtag/mslangid.hxx> @@ -66,27 +68,16 @@ GenericSalLayout::~GenericSalLayout() void GenericSalLayout::ParseFeatures(const OUString& aName) { - if (aName.indexOf(FontSelectPatternAttributes::FEAT_PREFIX) < 0) - return; + vcl::font::FeatureParser aParser(aName); + OUString sLanguage = aParser.getLanguage(); + if (!sLanguage.isEmpty()) + msLanguage = OUStringToOString(sLanguage, RTL_TEXTENCODING_ASCII_US); - OString sName = OUStringToOString(aName, RTL_TEXTENCODING_ASCII_US); - sName = sName.getToken(1, FontSelectPatternAttributes::FEAT_PREFIX); - sal_Int32 nIndex = 0; - do + for (std::pair<sal_uInt32, sal_uInt32> const & rPair : aParser.getFeatures()) { - OString sToken = sName.getToken(0, FontSelectPatternAttributes::FEAT_SEPARATOR, nIndex); - if (sToken.startsWith("lang=")) - { - msLanguage = sToken.getToken(1, '='); - } - else - { - hb_feature_t aFeature; - if (hb_feature_from_string(sToken.getStr(), sToken.getLength(), &aFeature)) - maFeatures.push_back(aFeature); - } + hb_feature_t aFeature { rPair.first, rPair.second, 0, SAL_MAX_UINT32 }; + maFeatures.push_back(aFeature); } - while (nIndex >= 0); } struct SubRun |