summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-07-30 10:38:43 +0200
committerTomaž Vajngerl <quikee@gmail.com>2018-07-31 18:29:39 +0200
commit74317ed5f794816bc9b33e087c5412833fbba420 (patch)
treeb192e0a424d3434d3cbc8cc0db17029b9d640554
parentaa2e694e8d9e22de94dbf21f81883f9af0e34ce9 (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.cxx27
-rw-r--r--cui/source/inc/FontFeaturesDialog.hxx2
-rw-r--r--cui/uiconfig/ui/fontfeaturesdialog.ui2
-rw-r--r--include/vcl/font/Feature.hxx10
-rw-r--r--include/vcl/font/FeatureParser.hxx2
-rw-r--r--vcl/inc/font/FeatureCollector.hxx6
-rw-r--r--vcl/qa/cppunit/FontFeatureTest.cxx15
-rw-r--r--vcl/source/font/Feature.cxx13
-rw-r--r--vcl/source/font/FeatureCollector.cxx112
-rw-r--r--vcl/source/font/FeatureParser.cxx2
-rw-r--r--vcl/source/outdev/font.cxx3
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;
}