LibreOffice Module cui (master)  1
FontFeaturesDialog.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  */
10 
11 #include <FontFeaturesDialog.hxx>
12 #include <rtl/ustrbuf.hxx>
14 #include <FontFeatures.hxx>
15 #include <svtools/colorcfg.hxx>
16 #include <unordered_set>
17 
18 using namespace css;
19 
20 namespace cui
21 {
22 FontFeaturesDialog::FontFeaturesDialog(weld::Window* pParent, OUString const& rFontName)
23  : GenericDialogController(pParent, "cui/ui/fontfeaturesdialog.ui", "FontFeaturesDialog")
24  , m_sFontName(rFontName)
25  , m_xContentWindow(m_xBuilder->weld_scrolled_window("contentWindow"))
26  , m_xContentGrid(m_xBuilder->weld_container("contentGrid"))
27  , m_xPreviewWindow(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWindow))
28 {
29  initialize();
30 }
31 
33 
34 static sal_Int32 makeEnumComboBox(weld::ComboBox& rNameBox,
35  vcl::font::FeatureDefinition const& rFeatureDefinition,
36  uint32_t nDefault)
37 {
38  sal_Int32 nRes = 0;
39  int count = 0;
40  for (vcl::font::FeatureParameter const& rParameter : rFeatureDefinition.getEnumParameters())
41  {
42  rNameBox.append(OUString::number(rParameter.getCode()), rParameter.getDescription());
43  if (rParameter.getCode() == nDefault)
44  nRes = count;
45  ++count;
46  }
47  return nRes;
48 }
49 
51 {
53  DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
54  std::vector<vcl::font::Feature> rFontFeatures = getFontFeatureList(m_sFontName, *aVDev);
55 
56  std::unordered_set<sal_uInt32> aDoneFeatures;
57  std::vector<vcl::font::Feature> rFilteredFontFeatures;
58 
59  for (vcl::font::Feature const& rFontFeature : rFontFeatures)
60  {
61  sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode;
62  if (!aDoneFeatures.insert(nFontFeatureCode).second)
63  continue;
64  rFilteredFontFeatures.push_back(rFontFeature);
65  }
66 
67  int nRowHeight = fillGrid(rFilteredFontFeatures);
68 
69  m_xContentWindow->set_size_request(
70  -1, std::min(std::max(m_xContentWindow->get_preferred_size().Height(),
71  m_xContentGrid->get_preferred_size().Height()),
72  static_cast<tools::Long>(300L)));
73 
74  if (nRowHeight)
75  {
76  // tdf#141333 use row height + the 6 px spacing of contentGrid
77  m_xContentWindow->vadjustment_set_step_increment(nRowHeight + 6);
78  }
79 
81 }
82 
83 int FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures)
84 {
85  int nRowHeight(0);
86 
88  auto aExistingFeatures = aParser.getFeaturesMap();
89 
90  sal_Int32 i = 0;
91  for (vcl::font::Feature const& rFontFeature : rFontFeatures)
92  {
93  sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode;
94 
95  vcl::font::FeatureDefinition aDefinition;
96  if (rFontFeature.m_aDefinition)
97  aDefinition = rFontFeature.m_aDefinition;
98  if (!aDefinition)
99  aDefinition = { nFontFeatureCode, nullptr };
100 
101  m_aFeatureItems.emplace_back(m_xContentGrid.get());
102 
103  uint32_t nValue = 0;
104  if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end())
105  nValue = aExistingFeatures.at(nFontFeatureCode);
106  else
107  nValue = aDefinition.getDefault();
108 
109  FontFeatureItem& aCurrentItem = m_aFeatureItems.back();
110  aCurrentItem.m_aFeatureCode = nFontFeatureCode;
111  aCurrentItem.m_nDefault = aDefinition.getDefault();
112 
113  sal_Int32 nGridPositionX = (i % 2) * 2;
114  sal_Int32 nGridPositionY = i / 2;
115  aCurrentItem.m_xContainer->set_grid_left_attach(nGridPositionX);
116  aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY);
117 
118  Link<weld::ComboBox&, void> aComboBoxSelectHandler
119  = LINK(this, FontFeaturesDialog, ComboBoxSelectedHdl);
120  Link<weld::Toggleable&, void> aCheckBoxToggleHandler
121  = LINK(this, FontFeaturesDialog, CheckBoxToggledHdl);
122 
123  if (aDefinition.getType() == vcl::font::FeatureParameterType::ENUM)
124  {
125  aCurrentItem.m_xText->set_label(aDefinition.getDescription());
126  aCurrentItem.m_xText->show();
127 
128  sal_Int32 nInit = makeEnumComboBox(*aCurrentItem.m_xCombo, aDefinition, nValue);
129 
130  aCurrentItem.m_xCombo->set_active(nInit);
131  aCurrentItem.m_xCombo->connect_changed(aComboBoxSelectHandler);
132  aCurrentItem.m_xCombo->show();
133  }
134  else
135  {
136  aCurrentItem.m_xCheck->set_active(nValue > 0);
137  aCurrentItem.m_xCheck->set_label(aDefinition.getDescription());
138  aCurrentItem.m_xCheck->connect_toggled(aCheckBoxToggleHandler);
139  aCurrentItem.m_xCheck->show();
140  }
141 
142  nRowHeight
143  = std::max<int>(nRowHeight, aCurrentItem.m_xContainer->get_preferred_size().Height());
144 
145  i++;
146  }
147 
148  return nRowHeight;
149 }
150 
152 {
153  vcl::Font rPreviewFont = m_aPreviewWindow.GetFont();
154  vcl::Font rPreviewFontCJK = m_aPreviewWindow.GetCJKFont();
155  vcl::Font rPreviewFontCTL = m_aPreviewWindow.GetCTLFont();
156 
157  OUString sNewFontName = createFontNameWithFeatures();
158 
159  rPreviewFont.SetFamilyName(sNewFontName);
160  rPreviewFontCJK.SetFamilyName(sNewFontName);
161  rPreviewFontCTL.SetFamilyName(sNewFontName);
162 
163  m_aPreviewWindow.SetFont(rPreviewFont, rPreviewFontCJK, rPreviewFontCTL);
164 }
165 
167 {
168  updateFontPreview();
169 }
170 
171 IMPL_LINK_NOARG(FontFeaturesDialog, ComboBoxSelectedHdl, weld::ComboBox&, void)
172 {
173  updateFontPreview();
174 }
175 
177 {
178  OUString sResultFontName;
179  OUStringBuffer sNameSuffix;
180  bool bFirst = true;
181 
182  for (const FontFeatureItem& rItem : m_aFeatureItems)
183  {
184  if (rItem.m_xCheck->get_visible())
185  {
186  if (sal_uInt32(rItem.m_xCheck->get_active()) != rItem.m_nDefault)
187  {
188  if (!bFirst)
189  sNameSuffix.append(vcl::font::FeatureSeparator);
190  else
191  bFirst = false;
192 
193  sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode));
194  if (!rItem.m_xCheck->get_active())
195  sNameSuffix.append("=0");
196  }
197  }
198  else if (rItem.m_xCombo->get_visible() && rItem.m_xText->get_visible())
199  {
200  sal_Int32 nSelection = rItem.m_xCombo->get_active_id().toInt32();
201  if (nSelection != int(rItem.m_nDefault))
202  {
203  if (!bFirst)
204  sNameSuffix.append(vcl::font::FeatureSeparator);
205  else
206  bFirst = false;
207 
208  sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode));
209  sNameSuffix.append("=");
210  sNameSuffix.append(OUString::number(nSelection));
211  }
212  }
213  }
214  sResultFontName = vcl::font::trimFontNameFeatures(m_sFontName);
215  if (!sNameSuffix.isEmpty())
216  sResultFontName
217  += OUStringChar(vcl::font::FeaturePrefix) + sNameSuffix.makeStringAndClear();
218  return sResultFontName;
219 }
220 
222 {
223  short nResult = GenericDialogController::run();
224  if (nResult == RET_OK)
225  {
227  }
228  return nResult;
229 }
230 
231 } // end svx namespace
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr const char FeaturePrefix
OUString getDescription() const
SvxFont & GetCTLFont()
IMPL_LINK_NOARG(ColorPickerDialog, ColorFieldControlModifydl, ColorFieldControl &, void)
OUString featureCodeAsString(uint32_t nFeature)
virtual short run() override
const std::vector< FeatureParameter > & getEnumParameters() const
SvxFont & GetCJKFont()
void append(const OUString &rId, const OUString &rStr)
uint32_t getDefault() const
std::unordered_map< uint32_t, uint32_t > getFeaturesMap() const
OUString trimFontNameFeatures(OUString const &rFontName)
static OutputDevice * GetDefaultDevice()
void SetFont(const SvxFont &rNormalFont, const SvxFont &rCJKFont, const SvxFont &rCTLFont)
std::vector< vcl::font::Feature > getFontFeatureList(OUString const &rFontName, VirtualDevice &rVDev)
SvxFont & GetFont()
constexpr const char FeatureSeparator
std::unique_ptr< weld::ScrolledWindow > m_xContentWindow
void SetFamilyName(const OUString &rFamilyName)
int i
std::unique_ptr< weld::Widget > m_xContainer
static sal_Int32 makeEnumComboBox(weld::ComboBox &rNameBox, vcl::font::FeatureDefinition const &rFeatureDefinition, uint32_t nDefault)
FeatureParameterType getType() const
int fillGrid(std::vector< vcl::font::Feature > const &rFontFeatures)
std::vector< FontFeatureItem > m_aFeatureItems
std::unique_ptr< weld::Label > m_xText
std::unique_ptr< weld::ComboBox > m_xCombo
RET_OK
SvxFontPrevWindow m_aPreviewWindow
std::unique_ptr< weld::Container > m_xContentGrid
std::unique_ptr< weld::CheckButton > m_xCheck
sal_Int16 nValue