summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-06-15 19:32:15 +0200
committerTomaž Vajngerl <quikee@gmail.com>2018-06-16 18:04:31 +0200
commitdc9ee533dc707cc10b99d537eaccc3ee5aa555fe (patch)
treebbe8c7547aac7b0440f874ed39945faa60a84276
parent099eef24da24d638fdf2c747d28040c9b3a30780 (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.hxx52
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/qa/cppunit/FontFeatureTest.cxx69
-rw-r--r--vcl/source/font/FeatureParser.cxx74
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx27
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