diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2018-07-30 10:38:43 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2018-07-31 18:29:39 +0200 |
commit | 74317ed5f794816bc9b33e087c5412833fbba420 (patch) | |
tree | b192e0a424d3434d3cbc8cc0db17029b9d640554 | |
parent | aa2e694e8d9e22de94dbf21f81883f9af0e34ce9 (diff) |
Font features: Use Graphite instead of HarfBuzz if available
When searching for font features, use Graphtie if it is available
instead of HarfBuzz, because HarfBuzz will only give a subset of
OpenType features in a Graphite font, but will ignore additional
features specific to Graphite.
Change-Id: I00c8790ee4d1e1ab906928f649d2a3e54163557f
Reviewed-on: https://gerrit.libreoffice.org/58306
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | cui/source/dialogs/FontFeaturesDialog.cxx | 27 | ||||
-rw-r--r-- | cui/source/inc/FontFeaturesDialog.hxx | 2 | ||||
-rw-r--r-- | cui/uiconfig/ui/fontfeaturesdialog.ui | 2 | ||||
-rw-r--r-- | include/vcl/font/Feature.hxx | 10 | ||||
-rw-r--r-- | include/vcl/font/FeatureParser.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/font/FeatureCollector.hxx | 6 | ||||
-rw-r--r-- | vcl/qa/cppunit/FontFeatureTest.cxx | 15 | ||||
-rw-r--r-- | vcl/source/font/Feature.cxx | 13 | ||||
-rw-r--r-- | vcl/source/font/FeatureCollector.cxx | 112 | ||||
-rw-r--r-- | vcl/source/font/FeatureParser.cxx | 2 | ||||
-rw-r--r-- | vcl/source/outdev/font.cxx | 3 |
11 files changed, 123 insertions, 71 deletions
diff --git a/cui/source/dialogs/FontFeaturesDialog.cxx b/cui/source/dialogs/FontFeaturesDialog.cxx index 21c71ce753b7..078e9a630a80 100644 --- a/cui/source/dialogs/FontFeaturesDialog.cxx +++ b/cui/source/dialogs/FontFeaturesDialog.cxx @@ -9,7 +9,6 @@ */ #include <FontFeaturesDialog.hxx> - #include <vcl/font/FeatureParser.hxx> #include <svx/dialmgr.hxx> @@ -56,20 +55,32 @@ void FontFeaturesDialog::initialize() if (!aVDev->GetFontFeatures(rFontFeatures)) return; - vcl::font::FeatureParser aParser(m_sFontName); - std::unordered_map<sal_uInt32, sal_uInt32> aExistingFeatures = aParser.getFeaturesMap(); - std::unordered_set<sal_uInt32> aDoneFeatures; + std::vector<vcl::font::Feature> rFilteredFontFeatures; - sal_Int32 i = 0; for (vcl::font::Feature const& rFontFeature : rFontFeatures) { sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode; - if (aDoneFeatures.find(nFontFeatureCode) != aDoneFeatures.end()) continue; - aDoneFeatures.insert(nFontFeatureCode); + rFilteredFontFeatures.push_back(rFontFeature); + } + + fillGrid(rFilteredFontFeatures); + + updateFontPreview(); +} + +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(); + + sal_Int32 i = 0; + for (vcl::font::Feature const& rFontFeature : rFontFeatures) + { + sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode; vcl::font::FeatureDefinition aDefinition; if (rFontFeature.m_aDefinition) @@ -138,8 +149,6 @@ void FontFeaturesDialog::initialize() i++; } - - updateFontPreview(); } void FontFeaturesDialog::updateFontPreview() diff --git a/cui/source/inc/FontFeaturesDialog.hxx b/cui/source/inc/FontFeaturesDialog.hxx index 533384d2e972..aa3a4aa22d0f 100644 --- a/cui/source/inc/FontFeaturesDialog.hxx +++ b/cui/source/inc/FontFeaturesDialog.hxx @@ -45,6 +45,8 @@ private: void initialize(); OUString createFontNameWithFeatures(); + void fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures); + DECL_LINK(ComboBoxSelectedHdl, ComboBox&, void); DECL_LINK(CheckBoxToggledHdl, CheckBox&, void); diff --git a/cui/uiconfig/ui/fontfeaturesdialog.ui b/cui/uiconfig/ui/fontfeaturesdialog.ui index f7ae893eb9c0..33964b4538bd 100644 --- a/cui/uiconfig/ui/fontfeaturesdialog.ui +++ b/cui/uiconfig/ui/fontfeaturesdialog.ui @@ -6,7 +6,7 @@ <object class="GtkDialog" id="FontFeaturesDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> - <property name="title" translatable="yes" context="newtabledialog|NewTableDialog">Font Features</property> + <property name="title" translatable="yes" context="fontfeaturesdialog|FontFeaturesDialog">Font Features</property> <property name="modal">True</property> <property name="default_width">1</property> <property name="default_height">1</property> diff --git a/include/vcl/font/Feature.hxx b/include/vcl/font/Feature.hxx index 9b0d29db3190..aca557e4e53a 100644 --- a/include/vcl/font/Feature.hxx +++ b/include/vcl/font/Feature.hxx @@ -35,6 +35,12 @@ enum class FeatureParameterType ENUM }; +enum class FeatureType +{ + OpenType, + Graphite +}; + struct VCL_DLLPUBLIC FeatureParameter { private: @@ -89,7 +95,11 @@ struct VCL_DLLPUBLIC FeatureID struct VCL_DLLPUBLIC Feature { + Feature(); + Feature(FeatureID const& rID, FeatureType eType); + FeatureID m_aID; + FeatureType m_eType; FeatureDefinition m_aDefinition; }; diff --git a/include/vcl/font/FeatureParser.hxx b/include/vcl/font/FeatureParser.hxx index 351caf19c7b7..3adc5fc0b0d0 100644 --- a/include/vcl/font/FeatureParser.hxx +++ b/include/vcl/font/FeatureParser.hxx @@ -44,7 +44,7 @@ public: return m_aFeatures; } - std::unordered_map<sal_uInt32, sal_uInt32> getFeaturesMap(); + std::unordered_map<sal_uInt32, sal_uInt32> getFeaturesMap() const; }; } // end font namespace diff --git a/vcl/inc/font/FeatureCollector.hxx b/vcl/inc/font/FeatureCollector.hxx index 6c278ca15188..aa6f51c3d83b 100644 --- a/vcl/inc/font/FeatureCollector.hxx +++ b/vcl/inc/font/FeatureCollector.hxx @@ -37,15 +37,15 @@ public: } private: - bool collectGraphiteFeatureDefinition(vcl::font::Feature& rFeature); - void collectForLanguage(hb_tag_t aTableTag, sal_uInt32 nScript, hb_tag_t aScriptTag, sal_uInt32 nLanguage, hb_tag_t aLanguageTag); void collectForScript(hb_tag_t aTableTag, sal_uInt32 nScript, hb_tag_t aScriptTag); + void collectForTable(hb_tag_t aTableTag); + bool collectGraphite(); public: - void collectForTable(hb_tag_t aTableTag); + bool collect(); }; } // end namespace font diff --git a/vcl/qa/cppunit/FontFeatureTest.cxx b/vcl/qa/cppunit/FontFeatureTest.cxx index 2e9507a3426c..7476162b976e 100644 --- a/vcl/qa/cppunit/FontFeatureTest.cxx +++ b/vcl/qa/cppunit/FontFeatureTest.cxx @@ -72,18 +72,23 @@ void FontFeatureTest::testGetFontFeatures() #if !defined(_WIN32) // periodically fails on windows tinderbox like tb77 with a value of 27 - CPPUNIT_ASSERT_EQUAL(size_t(20), rDefaultFontFeatures.size()); + CPPUNIT_ASSERT_EQUAL(size_t(53), rDefaultFontFeatures.size()); + + OUString aExpectedFeaturesString = "c2sc case dlig fina frac hlig liga lnum " + "locl onum pnum sa01 sa02 sa03 sa04 sa05 " + "sa06 sa07 sa08 salt sinf smcp ss01 ss02 " + "ss03 sups tnum zero ingl cpsp lith litt " + "itlc para algn arti circ dash dbls foot " + "frsp grkn hang lng minu nfsp name quot " + "texm thou vari caps ligc "; - OUString aExpectedFeaturesString = "aalt c2sc case dlig frac hlig liga lnum " - "onum pnum salt sinf smcp ss01 ss02 ss03 " - "sups tnum zero cpsp "; // periodically fails on windows tinderbox like tb72 with a missing "ss02" CPPUNIT_ASSERT_EQUAL(aExpectedFeaturesString, aFeaturesString); #endif // Check C2SC feature { - vcl::font::Feature& rFeature = rDefaultFontFeatures[1]; + vcl::font::Feature& rFeature = rDefaultFontFeatures[0]; CPPUNIT_ASSERT_EQUAL(vcl::font::featureCode("c2sc"), rFeature.m_aID.m_aFeatureCode); vcl::font::FeatureDefinition& rFracFeatureDefinition = rFeature.m_aDefinition; diff --git a/vcl/source/font/Feature.cxx b/vcl/source/font/Feature.cxx index a23a85fae952..7569467704ad 100644 --- a/vcl/source/font/Feature.cxx +++ b/vcl/source/font/Feature.cxx @@ -27,6 +27,19 @@ OUString featureCodeAsString(sal_uInt32 nFeature) return OStringToOUString(aString.data(), RTL_TEXTENCODING_ASCII_US); } +// Feature +Feature::Feature() + : m_aID({ 0, 0, 0 }) + , m_eType(FeatureType::OpenType) +{ +} + +Feature::Feature(FeatureID const& rID, FeatureType eType) + : m_aID(rID) + , m_eType(eType) +{ +} + // FeatureParameter FeatureParameter::FeatureParameter(sal_uInt32 nCode, OUString aDescription) diff --git a/vcl/source/font/FeatureCollector.cxx b/vcl/source/font/FeatureCollector.cxx index a8c1ff0d2548..4e1862388e9a 100644 --- a/vcl/source/font/FeatureCollector.cxx +++ b/vcl/source/font/FeatureCollector.cxx @@ -18,64 +18,65 @@ namespace vcl { namespace font { -bool FeatureCollector::collectGraphiteFeatureDefinition(vcl::font::Feature& rFeature) +bool FeatureCollector::collectGraphite() { gr_face* grFace = hb_graphite2_face_get_gr_face(m_pHbFace); + if (grFace == nullptr) return false; - bool bFound = false; - gr_uint16 nUILanguage = gr_uint16(m_eLanguageType); gr_uint16 nNumberOfFeatures = gr_face_n_fref(grFace); - gr_feature_val* pFeatures = gr_face_featureval_for_lang(grFace, rFeature.m_aID.m_aLanguageCode); - if (pFeatures) + for (gr_uint16 i = 0; i < nNumberOfFeatures; ++i) { - for (gr_uint16 i = 0; i < nNumberOfFeatures; ++i) + const gr_feature_ref* pFeatureRef = gr_face_fref(grFace, i); + gr_uint32 nFeatureCode = gr_fref_id(pFeatureRef); + + if (nFeatureCode == 0) // illegal feature code - skip + continue; + + gr_uint32 nLabelLength = 0; + void* pLabel = gr_fref_label(pFeatureRef, &nUILanguage, gr_utf8, &nLabelLength); + OUString sLabel(OUString::createFromAscii(static_cast<char*>(pLabel))); + gr_label_destroy(pLabel); + + std::vector<vcl::font::FeatureParameter> aParameters; + gr_uint16 nNumberOfValues = gr_fref_n_values(pFeatureRef); + + if (nNumberOfValues > 0) { - const gr_feature_ref* pFeatureRef = gr_face_fref(grFace, i); - gr_uint32 nFeatureCode = gr_fref_id(pFeatureRef); + for (gr_uint16 j = 0; j < nNumberOfValues; ++j) + { + gr_uint32 nValueLabelLength = 0; + void* pValueLabel = gr_fref_value_label(pFeatureRef, j, &nUILanguage, gr_utf8, + &nValueLabelLength); + OUString sValueLabel(OUString::createFromAscii(static_cast<char*>(pValueLabel))); + aParameters.emplace_back(sal_uInt32(j), sValueLabel); + gr_label_destroy(pValueLabel); + } - if (nFeatureCode == rFeature.m_aID.m_aFeatureCode) + auto eFeatureParameterType = vcl::font::FeatureParameterType::ENUM; + + // Check if the parameters are boolean + if (aParameters.size() == 2 + && (aParameters[0].getDescription() == "True" + || aParameters[0].getDescription() == "False")) { - gr_uint32 nLabelLength = 0; - void* pLabel = gr_fref_label(pFeatureRef, &nUILanguage, gr_utf8, &nLabelLength); - OUString sLabel(OUString::createFromAscii(static_cast<char*>(pLabel))); - gr_label_destroy(pLabel); - - std::vector<vcl::font::FeatureParameter> aParameters; - gr_uint16 nNumberOfValues = gr_fref_n_values(pFeatureRef); - for (gr_uint16 j = 0; j < nNumberOfValues; ++j) - { - gr_uint32 nValueLabelLength = 0; - void* pValueLabel = gr_fref_value_label(pFeatureRef, j, &nUILanguage, gr_utf8, - &nValueLabelLength); - OUString sValueLabel( - OUString::createFromAscii(static_cast<char*>(pValueLabel))); - aParameters.emplace_back(sal_uInt32(j), sValueLabel); - gr_label_destroy(pValueLabel); - } - - auto eFeatureParameterType = vcl::font::FeatureParameterType::ENUM; - - // Check if the parameters are boolean - if (aParameters.size() == 2 - && (aParameters[0].getDescription() == "True" - || aParameters[0].getDescription() == "False")) - { - eFeatureParameterType = vcl::font::FeatureParameterType::BOOL; - aParameters.clear(); - } - rFeature.m_aDefinition = vcl::font::FeatureDefinition( - rFeature.m_aID.m_aFeatureCode, sLabel, eFeatureParameterType, aParameters); - bFound = true; + eFeatureParameterType = vcl::font::FeatureParameterType::BOOL; + aParameters.clear(); } + + m_rFontFeatures.emplace_back( + FeatureID{ nFeatureCode, HB_OT_TAG_DEFAULT_SCRIPT, HB_OT_TAG_DEFAULT_LANGUAGE }, + vcl::font::FeatureType::Graphite); + vcl::font::Feature& rFeature = m_rFontFeatures.back(); + rFeature.m_aDefinition = vcl::font::FeatureDefinition( + nFeatureCode, sLabel, eFeatureParameterType, aParameters); } } - gr_featureval_destroy(pFeatures); - return bFound; + return true; } void FeatureCollector::collectForLanguage(hb_tag_t aTableTag, sal_uInt32 nScript, @@ -98,14 +99,11 @@ void FeatureCollector::collectForLanguage(hb_tag_t aTableTag, sal_uInt32 nScript vcl::font::Feature& rFeature = m_rFontFeatures.back(); rFeature.m_aID = { aFeatureTag, aScriptTag, aLanguageTag }; - if (!collectGraphiteFeatureDefinition(rFeature)) + FeatureDefinition aDefinition + = OpenTypeFeatureDefinitonList::get().getDefinition(aFeatureTag); + if (aDefinition) { - FeatureDefinition aDefinition - = OpenTypeFeatureDefinitonList::get().getDefinition(aFeatureTag); - if (aDefinition) - { - rFeature.m_aDefinition = vcl::font::FeatureDefinition(aDefinition); - } + rFeature.m_aDefinition = vcl::font::FeatureDefinition(aDefinition); } } } @@ -137,6 +135,22 @@ void FeatureCollector::collectForTable(hb_tag_t aTableTag) collectForScript(aTableTag, nScript, aScriptTags[nScript]); } +bool FeatureCollector::collect() +{ + gr_face* grFace = hb_graphite2_face_get_gr_face(m_pHbFace); + + if (grFace) + { + return collectGraphite(); + } + else + { + collectForTable(HB_OT_TAG_GSUB); // substitution + collectForTable(HB_OT_TAG_GPOS); // positioning + return true; + } +} + } // end namespace font } // end namespace vcl diff --git a/vcl/source/font/FeatureParser.cxx b/vcl/source/font/FeatureParser.cxx index d61c0a89cfd6..7085b94f19ef 100644 --- a/vcl/source/font/FeatureParser.cxx +++ b/vcl/source/font/FeatureParser.cxx @@ -57,7 +57,7 @@ FeatureParser::FeatureParser(OUString const& rFontName) } while (nIndex >= 0); } -std::unordered_map<sal_uInt32, sal_uInt32> FeatureParser::getFeaturesMap() +std::unordered_map<sal_uInt32, sal_uInt32> FeatureParser::getFeaturesMap() const { std::unordered_map<sal_uInt32, sal_uInt32> aResultMap; for (auto const& rPair : m_aFeatures) diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index d8015f6de0fa..de8fae5a578d 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -194,8 +194,7 @@ bool OutputDevice::GetFontFeatures(std::vector<vcl::font::Feature>& rFontFeature const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); vcl::font::FeatureCollector aFeatureCollector(pHbFace, rFontFeatures, eOfficeLanguage); - aFeatureCollector.collectForTable(HB_OT_TAG_GSUB); // substitution - aFeatureCollector.collectForTable(HB_OT_TAG_GPOS); // positioning + aFeatureCollector.collect(); return true; } |