1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <font/FeatureCollector.hxx>
11 #include <font/OpenTypeFeatureDefinitionList.hxx>
14 #include <hb-graphite2.h>
18 bool FeatureCollector::collectGraphite()
20 gr_face
* grFace
= hb_graphite2_face_get_gr_face(m_pHbFace
);
22 if (grFace
== nullptr)
25 gr_uint16 nUILanguage
= gr_uint16(m_eLanguageType
);
27 gr_uint16 nNumberOfFeatures
= gr_face_n_fref(grFace
);
28 gr_feature_val
* pfeatureValues
29 = gr_face_featureval_for_lang(grFace
, 0); // shame we don't know which lang
31 for (gr_uint16 i
= 0; i
< nNumberOfFeatures
; ++i
)
33 const gr_feature_ref
* pFeatureRef
= gr_face_fref(grFace
, i
);
34 gr_uint32 nFeatureCode
= gr_fref_id(pFeatureRef
);
36 if (nFeatureCode
== 0) // illegal feature code - skip
39 gr_uint16 nValue
= gr_fref_feature_value(pFeatureRef
, pfeatureValues
);
40 gr_uint32 nLabelLength
= 0;
41 void* pLabel
= gr_fref_label(pFeatureRef
, &nUILanguage
, gr_utf8
, &nLabelLength
);
42 OUString
sLabel(OUString::createFromAscii(static_cast<char*>(pLabel
)));
43 gr_label_destroy(pLabel
);
45 std::vector
<vcl::font::FeatureParameter
> aParameters
;
46 gr_uint16 nNumberOfValues
= gr_fref_n_values(pFeatureRef
);
48 if (nNumberOfValues
> 0)
50 for (gr_uint16 j
= 0; j
< nNumberOfValues
; ++j
)
52 gr_uint32 nValueLabelLength
= 0;
53 void* pValueLabel
= gr_fref_value_label(pFeatureRef
, j
, &nUILanguage
, gr_utf8
,
55 OUString
sValueLabel(OUString::createFromAscii(static_cast<char*>(pValueLabel
)));
56 gr_uint16 nParamValue
= gr_fref_value(pFeatureRef
, j
);
57 aParameters
.emplace_back(sal_uInt32(nParamValue
), sValueLabel
);
58 gr_label_destroy(pValueLabel
);
61 auto eFeatureParameterType
= vcl::font::FeatureParameterType::ENUM
;
63 // Check if the parameters are boolean
64 if (aParameters
.size() == 2
65 && (aParameters
[0].getDescription() == "True"
66 || aParameters
[0].getDescription() == "False"))
68 eFeatureParameterType
= vcl::font::FeatureParameterType::BOOL
;
72 m_rFontFeatures
.emplace_back(
73 FeatureID
{ nFeatureCode
, HB_OT_TAG_DEFAULT_SCRIPT
, HB_OT_TAG_DEFAULT_LANGUAGE
},
74 vcl::font::FeatureType::Graphite
);
75 vcl::font::Feature
& rFeature
= m_rFontFeatures
.back();
76 rFeature
.m_aDefinition
= vcl::font::FeatureDefinition(
77 nFeatureCode
, sLabel
, eFeatureParameterType
, aParameters
, sal_uInt32(nValue
));
80 gr_featureval_destroy(pfeatureValues
);
84 void FeatureCollector::collectForLanguage(hb_tag_t aTableTag
, sal_uInt32 nScript
,
85 hb_tag_t aScriptTag
, sal_uInt32 nLanguage
,
86 hb_tag_t aLanguageTag
)
88 unsigned int nFeatureCount
= hb_ot_layout_language_get_feature_tags(
89 m_pHbFace
, aTableTag
, nScript
, nLanguage
, 0, nullptr, nullptr);
90 std::vector
<hb_tag_t
> aFeatureTags(nFeatureCount
);
91 hb_ot_layout_language_get_feature_tags(m_pHbFace
, aTableTag
, nScript
, nLanguage
, 0,
92 &nFeatureCount
, aFeatureTags
.data());
93 aFeatureTags
.resize(nFeatureCount
);
95 for (hb_tag_t aFeatureTag
: aFeatureTags
)
97 if (OpenTypeFeatureDefinitionList::get().isRequired(aFeatureTag
))
100 m_rFontFeatures
.emplace_back();
101 vcl::font::Feature
& rFeature
= m_rFontFeatures
.back();
102 rFeature
.m_aID
= { aFeatureTag
, aScriptTag
, aLanguageTag
};
104 FeatureDefinition aDefinition
105 = OpenTypeFeatureDefinitionList::get().getDefinition(aFeatureTag
);
108 rFeature
.m_aDefinition
= aDefinition
;
113 void FeatureCollector::collectForScript(hb_tag_t aTableTag
, sal_uInt32 nScript
, hb_tag_t aScriptTag
)
115 collectForLanguage(aTableTag
, nScript
, aScriptTag
, HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
,
116 HB_OT_TAG_DEFAULT_LANGUAGE
);
118 unsigned int nLanguageCount
119 = hb_ot_layout_script_get_language_tags(m_pHbFace
, aTableTag
, nScript
, 0, nullptr, nullptr);
120 std::vector
<hb_tag_t
> aLanguageTags(nLanguageCount
);
121 hb_ot_layout_script_get_language_tags(m_pHbFace
, aTableTag
, nScript
, 0, &nLanguageCount
,
122 aLanguageTags
.data());
123 aLanguageTags
.resize(nLanguageCount
);
124 for (sal_uInt32 nLanguage
= 0; nLanguage
< sal_uInt32(nLanguageCount
); ++nLanguage
)
125 collectForLanguage(aTableTag
, nScript
, aScriptTag
, nLanguage
, aLanguageTags
[nLanguage
]);
128 void FeatureCollector::collectForTable(hb_tag_t aTableTag
)
130 unsigned int nScriptCount
131 = hb_ot_layout_table_get_script_tags(m_pHbFace
, aTableTag
, 0, nullptr, nullptr);
132 std::vector
<hb_tag_t
> aScriptTags(nScriptCount
);
133 hb_ot_layout_table_get_script_tags(m_pHbFace
, aTableTag
, 0, &nScriptCount
, aScriptTags
.data());
134 aScriptTags
.resize(nScriptCount
);
136 for (sal_uInt32 nScript
= 0; nScript
< sal_uInt32(nScriptCount
); ++nScript
)
137 collectForScript(aTableTag
, nScript
, aScriptTags
[nScript
]);
140 bool FeatureCollector::collect()
142 gr_face
* grFace
= hb_graphite2_face_get_gr_face(m_pHbFace
);
146 return collectGraphite();
150 collectForTable(HB_OT_TAG_GSUB
); // substitution
151 collectForTable(HB_OT_TAG_GPOS
); // positioning
156 } // end namespace vcl::font
158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */