[Libreoffice-commits] core.git: include/vcl vcl/Library_vcl.mk vcl/qa vcl/source

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Sat Jun 16 16:04:51 UTC 2018


 include/vcl/font/FeatureParser.hxx |   52 ++++++++++++++++++++++++++
 vcl/Library_vcl.mk                 |    1 
 vcl/qa/cppunit/FontFeatureTest.cxx |   69 ++++++++++++++++++++++++++++++++++
 vcl/source/font/FeatureParser.cxx  |   74 +++++++++++++++++++++++++++++++++++++
 vcl/source/gdi/CommonSalLayout.cxx |   27 ++++---------
 5 files changed, 204 insertions(+), 19 deletions(-)

New commits:
commit dc9ee533dc707cc10b99d537eaccc3ee5aa555fe
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jun 15 19:32:15 2018 +0200

    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 at gmail.com>

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


More information about the Libreoffice-commits mailing list