LibreOffice Module vcl (master)  1
FeatureCollector.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  */
9 
12 
13 #include <hb-ot.h>
14 #include <hb-graphite2.h>
15 
16 namespace vcl::font
17 {
19 {
20  gr_face* grFace = hb_graphite2_face_get_gr_face(m_pHbFace);
21 
22  if (grFace == nullptr)
23  return false;
24 
25  gr_uint16 nUILanguage = gr_uint16(m_eLanguageType);
26 
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
30 
31  for (gr_uint16 i = 0; i < nNumberOfFeatures; ++i)
32  {
33  const gr_feature_ref* pFeatureRef = gr_face_fref(grFace, i);
34  gr_uint32 nFeatureCode = gr_fref_id(pFeatureRef);
35 
36  if (nFeatureCode == 0) // illegal feature code - skip
37  continue;
38 
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);
44 
45  std::vector<vcl::font::FeatureParameter> aParameters;
46  gr_uint16 nNumberOfValues = gr_fref_n_values(pFeatureRef);
47 
48  if (nNumberOfValues > 0)
49  {
50  for (gr_uint16 j = 0; j < nNumberOfValues; ++j)
51  {
52  gr_uint32 nValueLabelLength = 0;
53  void* pValueLabel = gr_fref_value_label(pFeatureRef, j, &nUILanguage, gr_utf8,
54  &nValueLabelLength);
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);
59  }
60 
61  auto eFeatureParameterType = vcl::font::FeatureParameterType::ENUM;
62 
63  // Check if the parameters are boolean
64  if (aParameters.size() == 2
65  && (aParameters[0].getDescription() == "True"
66  || aParameters[0].getDescription() == "False"))
67  {
68  eFeatureParameterType = vcl::font::FeatureParameterType::BOOL;
69  aParameters.clear();
70  }
71 
72  m_rFontFeatures.emplace_back(
73  FeatureID{ nFeatureCode, HB_OT_TAG_DEFAULT_SCRIPT, HB_OT_TAG_DEFAULT_LANGUAGE },
75  vcl::font::Feature& rFeature = m_rFontFeatures.back();
77  nFeatureCode, sLabel, eFeatureParameterType, aParameters, sal_uInt32(nValue));
78  }
79  }
80  gr_featureval_destroy(pfeatureValues);
81  return true;
82 }
83 
84 void FeatureCollector::collectForLanguage(hb_tag_t aTableTag, sal_uInt32 nScript,
85  hb_tag_t aScriptTag, sal_uInt32 nLanguage,
86  hb_tag_t aLanguageTag)
87 {
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);
94 
95  for (hb_tag_t aFeatureTag : aFeatureTags)
96  {
97  if (OpenTypeFeatureDefinitionList::get().isRequired(aFeatureTag))
98  continue;
99 
100  m_rFontFeatures.emplace_back();
101  vcl::font::Feature& rFeature = m_rFontFeatures.back();
102  rFeature.m_aID = { aFeatureTag, aScriptTag, aLanguageTag };
103 
104  FeatureDefinition aDefinition
105  = OpenTypeFeatureDefinitionList::get().getDefinition(aFeatureTag);
106  if (aDefinition)
107  {
108  rFeature.m_aDefinition = aDefinition;
109  }
110  }
111 }
112 
113 void FeatureCollector::collectForScript(hb_tag_t aTableTag, sal_uInt32 nScript, hb_tag_t aScriptTag)
114 {
115  collectForLanguage(aTableTag, nScript, aScriptTag, HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
116  HB_OT_TAG_DEFAULT_LANGUAGE);
117 
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]);
126 }
127 
128 void FeatureCollector::collectForTable(hb_tag_t aTableTag)
129 {
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);
135 
136  for (sal_uInt32 nScript = 0; nScript < sal_uInt32(nScriptCount); ++nScript)
137  collectForScript(aTableTag, nScript, aScriptTags[nScript]);
138 }
139 
141 {
142  gr_face* grFace = hb_graphite2_face_get_gr_face(m_pHbFace);
143 
144  if (grFace)
145  {
146  return collectGraphite();
147  }
148  else
149  {
150  collectForTable(HB_OT_TAG_GSUB); // substitution
151  collectForTable(HB_OT_TAG_GPOS); // positioning
152  return true;
153  }
154 }
155 
156 } // end namespace vcl::font
157 
158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
FeatureID m_aID
Definition: Feature.hxx:99
std::vector< vcl::font::Feature > & m_rFontFeatures
int i
void collectForLanguage(hb_tag_t aTableTag, sal_uInt32 nScript, hb_tag_t aScriptTag, sal_uInt32 nLanguage, hb_tag_t aLanguageTag)
void collectForTable(hb_tag_t aTableTag)
void collectForScript(hb_tag_t aTableTag, sal_uInt32 nScript, hb_tag_t aScriptTag)
FeatureDefinition m_aDefinition
Definition: Feature.hxx:101
sal_Int16 nValue