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

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Mar 11 23:54:53 UTC 2019


 cui/source/dialogs/FontFeaturesDialog.cxx |    4 
 include/vcl/font/Feature.hxx              |   44 ++++---
 include/vcl/font/FeatureParser.hxx        |   11 -
 vcl/qa/cppunit/FontFeatureTest.cxx        |  182 ++++++++++++++++++++++++++----
 vcl/source/font/Feature.cxx               |   35 ++++-
 vcl/source/font/FeatureParser.cxx         |   35 ++---
 vcl/source/gdi/CommonSalLayout.cxx        |    4 
 7 files changed, 240 insertions(+), 75 deletions(-)

New commits:
commit 45deb5b714d2d011eb2a5ad91721a9c2c508a426
Author:     Khaled Hosny <khaledhosny at eglug.org>
AuthorDate: Mon Mar 11 20:55:24 2019 +0200
Commit:     Khaled Hosny <khaledhosny at eglug.org>
CommitDate: Tue Mar 12 00:54:29 2019 +0100

    tdf#123304: Allow the full feature syntax as pre 6.2
    
    Fix regression from:
    
    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
    
    Where hb_feature_from_string() was replaced by a simple parser that supports
    avery limited subset of the syntax it supports (as documented in
    https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-feature-from-string)
    
    Change-Id: I613190a677d24183e8c718fcfcaf9cf9b37a1e8f
    Reviewed-on: https://gerrit.libreoffice.org/69062
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
    Tested-by: Khaled Hosny <khaledhosny at eglug.org>

diff --git a/cui/source/dialogs/FontFeaturesDialog.cxx b/cui/source/dialogs/FontFeaturesDialog.cxx
index 85a07e63971b..b4dd8e7fc63e 100644
--- a/cui/source/dialogs/FontFeaturesDialog.cxx
+++ b/cui/source/dialogs/FontFeaturesDialog.cxx
@@ -76,7 +76,7 @@ void FontFeaturesDialog::initialize()
 void FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures)
 {
     vcl::font::FeatureParser aParser(m_sFontName);
-    std::unordered_map<sal_uInt32, sal_uInt32> aExistingFeatures = aParser.getFeaturesMap();
+    auto aExistingFeatures = aParser.getFeaturesMap();
 
     sal_Int32 i = 0;
     for (vcl::font::Feature const& rFontFeature : rFontFeatures)
@@ -91,7 +91,7 @@ void FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFe
 
         m_aFeatureItems.emplace_back(m_xContentGrid.get());
 
-        sal_uInt32 nValue = 0;
+        uint32_t nValue = 0;
         if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end())
             nValue = aExistingFeatures.at(nFontFeatureCode);
 
diff --git a/include/vcl/font/Feature.hxx b/include/vcl/font/Feature.hxx
index 85e0d1bcfd0d..390abe33f8b7 100644
--- a/include/vcl/font/Feature.hxx
+++ b/include/vcl/font/Feature.hxx
@@ -18,13 +18,13 @@ namespace vcl
 {
 namespace font
 {
-constexpr sal_uInt32 featureCode(const char sFeature[4])
+constexpr uint32_t featureCode(const char sFeature[4])
 {
-    return static_cast<sal_uInt32>(sFeature[0]) << 24U | static_cast<sal_uInt32>(sFeature[1]) << 16U
-           | static_cast<sal_uInt32>(sFeature[2]) << 8U | static_cast<sal_uInt32>(sFeature[3]);
+    return static_cast<uint32_t>(sFeature[0]) << 24U | static_cast<uint32_t>(sFeature[1]) << 16U
+           | static_cast<uint32_t>(sFeature[2]) << 8U | static_cast<uint32_t>(sFeature[3]);
 }
 
-VCL_DLLPUBLIC OUString featureCodeAsString(sal_uInt32 nFeature);
+VCL_DLLPUBLIC OUString featureCodeAsString(uint32_t nFeature);
 
 enum class FeatureParameterType
 {
@@ -41,22 +41,22 @@ enum class FeatureType
 struct VCL_DLLPUBLIC FeatureParameter
 {
 private:
-    sal_uInt32 m_nCode;
+    uint32_t m_nCode;
     OUString m_sDescription;
     const char* m_pDescriptionID;
 
 public:
-    FeatureParameter(sal_uInt32 nCode, OUString aDescription);
-    FeatureParameter(sal_uInt32 nCode, const char* pDescriptionID);
+    FeatureParameter(uint32_t nCode, OUString aDescription);
+    FeatureParameter(uint32_t nCode, const char* pDescriptionID);
 
-    sal_uInt32 getCode() const;
+    uint32_t getCode() const;
     OUString getDescription() const;
 };
 
 class VCL_DLLPUBLIC FeatureDefinition
 {
 private:
-    sal_uInt32 m_nCode;
+    uint32_t m_nCode;
     OUString m_sDescription;
     const char* m_pDescriptionID;
     OUString m_sNumericPart;
@@ -66,18 +66,18 @@ private:
 
 public:
     FeatureDefinition();
-    FeatureDefinition(sal_uInt32 nCode, OUString const& rDescription,
+    FeatureDefinition(uint32_t nCode, OUString const& rDescription,
                       FeatureParameterType eType = FeatureParameterType::BOOL,
                       std::vector<FeatureParameter> const& rEnumParameters
                       = std::vector<FeatureParameter>{});
-    FeatureDefinition(sal_uInt32 nCode, const char* pDescriptionID,
+    FeatureDefinition(uint32_t nCode, const char* pDescriptionID,
                       OUString const& rNumericPart = OUString());
-    FeatureDefinition(sal_uInt32 nCode, const char* pDescriptionID,
+    FeatureDefinition(uint32_t nCode, const char* pDescriptionID,
                       std::vector<FeatureParameter> aEnumParameters);
 
     const std::vector<FeatureParameter>& getEnumParameters() const;
     OUString getDescription() const;
-    sal_uInt32 getCode() const;
+    uint32_t getCode() const;
     FeatureParameterType getType() const;
 
     operator bool() const;
@@ -85,9 +85,9 @@ public:
 
 struct VCL_DLLPUBLIC FeatureID
 {
-    sal_uInt32 m_aFeatureCode;
-    sal_uInt32 m_aScriptCode;
-    sal_uInt32 m_aLanguageCode;
+    uint32_t m_aFeatureCode;
+    uint32_t m_aScriptCode;
+    uint32_t m_aLanguageCode;
 };
 
 struct VCL_DLLPUBLIC Feature
@@ -100,6 +100,18 @@ struct VCL_DLLPUBLIC Feature
     FeatureDefinition m_aDefinition;
 };
 
+// This is basically duplicates hb_feature_t to avoid including HarfBuzz
+// headers here, so the member types should remain compatible.
+struct VCL_DLLPUBLIC FeatureSetting
+{
+    FeatureSetting(OString feature);
+
+    uint32_t m_nTag;
+    uint32_t m_nValue;
+    unsigned int m_nStart;
+    unsigned int m_nEnd;
+};
+
 } // end font namespace
 
 } // end vcl namespace
diff --git a/include/vcl/font/FeatureParser.hxx b/include/vcl/font/FeatureParser.hxx
old mode 100644
new mode 100755
index 37e8b0d6196d..5674e2d3116c
--- a/include/vcl/font/FeatureParser.hxx
+++ b/include/vcl/font/FeatureParser.hxx
@@ -15,6 +15,8 @@
 #include <vector>
 #include <unordered_map>
 
+#include <vcl/font/Feature.hxx>
+
 namespace vcl
 {
 namespace font
@@ -29,19 +31,16 @@ class VCL_DLLPUBLIC FeatureParser
 {
 private:
     OUString m_sLanguage;
-    std::vector<std::pair<sal_uInt32, sal_uInt32>> m_aFeatures;
+    std::vector<FeatureSetting> m_aFeatures;
 
 public:
     FeatureParser(OUString const& sFontName);
 
     OUString const& getLanguage() const { return m_sLanguage; }
 
-    std::vector<std::pair<sal_uInt32, sal_uInt32>> const& getFeatures() const
-    {
-        return m_aFeatures;
-    }
+    std::vector<FeatureSetting> const& getFeatures() const { return m_aFeatures; }
 
-    std::unordered_map<sal_uInt32, sal_uInt32> getFeaturesMap() const;
+    std::unordered_map<uint32_t, uint32_t> getFeaturesMap() const;
 };
 
 } // end font namespace
diff --git a/vcl/qa/cppunit/FontFeatureTest.cxx b/vcl/qa/cppunit/FontFeatureTest.cxx
index 6a66eb1c70b5..47e610f50018 100644
--- a/vcl/qa/cppunit/FontFeatureTest.cxx
+++ b/vcl/qa/cppunit/FontFeatureTest.cxx
@@ -119,17 +119,17 @@ void FontFeatureTest::testGetFontFeatures()
 
         vcl::font::FeatureParameter const& rParameter1
             = rFracFeatureDefinition.getEnumParameters()[0];
-        CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), rParameter1.getCode());
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), rParameter1.getCode());
         CPPUNIT_ASSERT(!rParameter1.getDescription().isEmpty());
 
         vcl::font::FeatureParameter const& rParameter2
             = rFracFeatureDefinition.getEnumParameters()[1];
-        CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), rParameter2.getCode());
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), rParameter2.getCode());
         CPPUNIT_ASSERT(!rParameter2.getDescription().isEmpty());
 
         vcl::font::FeatureParameter const& rParameter3
             = rFracFeatureDefinition.getEnumParameters()[2];
-        CPPUNIT_ASSERT_EQUAL(sal_uInt32(2), rParameter3.getCode());
+        CPPUNIT_ASSERT_EQUAL(uint32_t(2), rParameter3.getCode());
         CPPUNIT_ASSERT(!rParameter2.getDescription().isEmpty());
     }
 #endif // HAVE_MORE_FONTS
@@ -146,44 +146,184 @@ void FontFeatureTest::testParseFeature()
         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(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
     }
     { // 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);
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(5), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, explicit zero value
+        vcl::font::FeatureParser aParser("Font name:abcd=0");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, using plus prefix
+        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].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, using minus prefix
+        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].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, with empty character range
+        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].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with empty character range
+        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].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with start character range
+        vcl::font::FeatureParser aParser("Font name:abcd[3:]");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(-1), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with end character range
+        vcl::font::FeatureParser aParser("Font name:abcd[:3]");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(0), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with character range
+        vcl::font::FeatureParser aParser("Font name:abcd[3:6]");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with character range
+        vcl::font::FeatureParser aParser("Font name:abcd[3]");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(4), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with character range and value
+        vcl::font::FeatureParser aParser("Font name:abcd[3:6]=2");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with character range and 0 value
+        vcl::font::FeatureParser aParser("Font name:abcd[3:6]=0");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with character range and minus prefix
+        vcl::font::FeatureParser aParser("Font name:-abcd[3:6]");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(3), aFeatures[0].m_nStart);
+        CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(6), aFeatures[0].m_nEnd);
+    }
+    { // One feature specified, with CSS on
+        vcl::font::FeatureParser aParser("Font name:\"abcd\" on");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, with CSS off
+        vcl::font::FeatureParser aParser("Font name:'abcd' off");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[0].m_nValue);
+    }
+    { // One feature specified, with CSS value
+        vcl::font::FeatureParser aParser("Font name:\"abcd\" 2");
+        CPPUNIT_ASSERT_EQUAL(size_t(1), aParser.getFeatures().size());
+        auto aFeatures = aParser.getFeatures();
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(2), aFeatures[0].m_nValue);
     }
     { // 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("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
 
-        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("bcde"), aFeatures[1].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[1].m_nValue);
 
-        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("efgh"), aFeatures[2].first);
-        CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aFeatures[2].second);
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("efgh"), aFeatures[2].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[2].m_nValue);
     }
     {
         // Multiple features specified, explicit values
         // Only 4 char parameter names supported - "toolong" is too long and ignored
-        // 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());
+        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("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
+
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("bcde"), aFeatures[1].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(0), aFeatures[1].m_nValue);
 
-        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("cdef"), aFeatures[1].first);
-        CPPUNIT_ASSERT_EQUAL(sal_uInt32(3), aFeatures[1].second);
+        CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("cdef"), aFeatures[2].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(3), aFeatures[2].m_nValue);
     }
     {
         // Special case - "lang" is parsed specially and access separately not as a feature.
@@ -192,8 +332,8 @@ void FontFeatureTest::testParseFeature()
         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(vcl::font::featureCode("abcd"), aFeatures[0].m_nTag);
+        CPPUNIT_ASSERT_EQUAL(uint32_t(1), aFeatures[0].m_nValue);
 
         CPPUNIT_ASSERT_EQUAL(OUString("slo"), aParser.getLanguage());
     }
diff --git a/vcl/source/font/Feature.cxx b/vcl/source/font/Feature.cxx
index 07810c1b011b..3a809cb11e8a 100644
--- a/vcl/source/font/Feature.cxx
+++ b/vcl/source/font/Feature.cxx
@@ -13,11 +13,13 @@
 #include <strings.hrc>
 #include <svdata.hxx>
 
+#include <hb.h>
+
 namespace vcl
 {
 namespace font
 {
-OUString featureCodeAsString(sal_uInt32 nFeature)
+OUString featureCodeAsString(uint32_t nFeature)
 {
     std::vector<sal_Char> aString(5, 0);
     aString[0] = sal_Char(nFeature >> 24 & 0xff);
@@ -41,16 +43,33 @@ Feature::Feature(FeatureID const& rID, FeatureType eType)
 {
 }
 
+// FeatureSetting
+FeatureSetting::FeatureSetting(OString feature)
+    : m_nTag(0)
+    , m_nValue(0)
+    , m_nStart(0)
+    , m_nEnd(0)
+{
+    hb_feature_t aFeat;
+    if (hb_feature_from_string(feature.getStr(), feature.getLength(), &aFeat))
+    {
+        m_nTag = aFeat.tag;
+        m_nValue = aFeat.value;
+        m_nStart = aFeat.start;
+        m_nEnd = aFeat.end;
+    }
+}
+
 // FeatureParameter
 
-FeatureParameter::FeatureParameter(sal_uInt32 nCode, OUString aDescription)
+FeatureParameter::FeatureParameter(uint32_t nCode, OUString aDescription)
     : m_nCode(nCode)
     , m_sDescription(std::move(aDescription))
     , m_pDescriptionID(nullptr)
 {
 }
 
-FeatureParameter::FeatureParameter(sal_uInt32 nCode, const char* pDescriptionID)
+FeatureParameter::FeatureParameter(uint32_t nCode, const char* pDescriptionID)
     : m_nCode(nCode)
     , m_pDescriptionID(pDescriptionID)
 {
@@ -68,7 +87,7 @@ OUString FeatureParameter::getDescription() const
     return aReturnString;
 }
 
-sal_uInt32 FeatureParameter::getCode() const { return m_nCode; }
+uint32_t FeatureParameter::getCode() const { return m_nCode; }
 
 // FeatureDefinition
 
@@ -79,7 +98,7 @@ FeatureDefinition::FeatureDefinition()
 {
 }
 
-FeatureDefinition::FeatureDefinition(sal_uInt32 nCode, OUString const& rDescription,
+FeatureDefinition::FeatureDefinition(uint32_t nCode, OUString const& rDescription,
                                      FeatureParameterType eType,
                                      std::vector<FeatureParameter> const& rEnumParameters)
     : m_nCode(nCode)
@@ -90,7 +109,7 @@ FeatureDefinition::FeatureDefinition(sal_uInt32 nCode, OUString const& rDescript
 {
 }
 
-FeatureDefinition::FeatureDefinition(sal_uInt32 nCode, const char* pDescriptionID,
+FeatureDefinition::FeatureDefinition(uint32_t nCode, const char* pDescriptionID,
                                      OUString const& rNumericPart)
     : m_nCode(nCode)
     , m_pDescriptionID(pDescriptionID)
@@ -99,7 +118,7 @@ FeatureDefinition::FeatureDefinition(sal_uInt32 nCode, const char* pDescriptionI
 {
 }
 
-FeatureDefinition::FeatureDefinition(sal_uInt32 nCode, const char* pDescriptionID,
+FeatureDefinition::FeatureDefinition(uint32_t nCode, const char* pDescriptionID,
                                      std::vector<FeatureParameter> aEnumParameters)
     : m_nCode(nCode)
     , m_pDescriptionID(pDescriptionID)
@@ -132,7 +151,7 @@ OUString FeatureDefinition::getDescription() const
     }
 }
 
-sal_uInt32 FeatureDefinition::getCode() const { return m_nCode; }
+uint32_t FeatureDefinition::getCode() const { return m_nCode; }
 
 FeatureParameterType FeatureDefinition::getType() const { return m_eType; }
 
diff --git a/vcl/source/font/FeatureParser.cxx b/vcl/source/font/FeatureParser.cxx
index a7626a564942..b8afe2f36b06 100644
--- a/vcl/source/font/FeatureParser.cxx
+++ b/vcl/source/font/FeatureParser.cxx
@@ -32,7 +32,7 @@ FeatureParser::FeatureParser(OUString const& rFontName)
     if (nPrefixIdx < 0)
         return;
 
-    OUString sName = rFontName.getToken(0, vcl::font::FeaturePrefix, ++nPrefixIdx);
+    OUString sName = rFontName.copy(++nPrefixIdx);
     sal_Int32 nIndex = 0;
     do
     {
@@ -40,33 +40,28 @@ FeatureParser::FeatureParser(OUString const& rFontName)
 
         sal_Int32 nInnerIdx{ 0 };
         OUString sID = sToken.getToken(0, '=', nInnerIdx);
-        OUString sValue = sToken.getToken(0, '=', nInnerIdx);
 
-        if (sID.getLength() == 4 && sValue != "0")
+        if (sID == "lang")
         {
-            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);
-            }
+            m_sLanguage = sToken.getToken(0, '=', nInnerIdx);
+        }
+        else
+        {
+            OString sFeature = OUStringToOString(sToken, RTL_TEXTENCODING_ASCII_US);
+            FeatureSetting aFeature(sFeature);
+            if (aFeature.m_nTag != 0)
+                m_aFeatures.push_back(aFeature);
         }
     } while (nIndex >= 0);
 }
 
-std::unordered_map<sal_uInt32, sal_uInt32> FeatureParser::getFeaturesMap() const
+std::unordered_map<uint32_t, uint32_t> FeatureParser::getFeaturesMap() const
 {
-    std::unordered_map<sal_uInt32, sal_uInt32> aResultMap;
-    for (auto const& rPair : m_aFeatures)
+    std::unordered_map<uint32_t, uint32_t> aResultMap;
+    for (auto const& rFeat : m_aFeatures)
     {
-        aResultMap.emplace(rPair);
+        if (rFeat.m_nValue != 0)
+            aResultMap.emplace(rFeat.m_nTag, rFeat.m_nValue);
     }
     return aResultMap;
 }
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 94dfa3b427a4..bfa4e1a2f503 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -74,9 +74,9 @@ void GenericSalLayout::ParseFeatures(const OUString& aName)
     if (!sLanguage.isEmpty())
         msLanguage = OUStringToOString(sLanguage, RTL_TEXTENCODING_ASCII_US);
 
-    for (std::pair<sal_uInt32, sal_uInt32> const & rPair : aParser.getFeatures())
+    for (auto const &rFeat : aParser.getFeatures())
     {
-        hb_feature_t aFeature { rPair.first, rPair.second, 0, SAL_MAX_UINT32 };
+        hb_feature_t aFeature { rFeat.m_nTag, rFeat.m_nValue, rFeat.m_nStart, rFeat.m_nEnd };
         maFeatures.push_back(aFeature);
     }
 }


More information about the Libreoffice-commits mailing list