diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /cui/source/dialogs/FontFeaturesDialog.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cui/source/dialogs/FontFeaturesDialog.cxx')
-rw-r--r-- | cui/source/dialogs/FontFeaturesDialog.cxx | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/cui/source/dialogs/FontFeaturesDialog.cxx b/cui/source/dialogs/FontFeaturesDialog.cxx new file mode 100644 index 0000000000..e9aba0a6e4 --- /dev/null +++ b/cui/source/dialogs/FontFeaturesDialog.cxx @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <FontFeaturesDialog.hxx> +#include <rtl/ustrbuf.hxx> +#include <utility> +#include <vcl/font/FeatureParser.hxx> +#include <FontFeatures.hxx> +#include <unordered_set> + +using namespace css; + +namespace cui +{ +FontFeaturesDialog::FontFeaturesDialog(weld::Window* pParent, OUString aFontName) + : GenericDialogController(pParent, "cui/ui/fontfeaturesdialog.ui", "FontFeaturesDialog") + , m_sFontName(std::move(aFontName)) + , m_xContentWindow(m_xBuilder->weld_scrolled_window("contentWindow")) + , m_xContentBox(m_xBuilder->weld_container("contentBox")) + , m_xContentGrid(m_xBuilder->weld_container("contentGrid")) + , m_xStylisticSetsBox(m_xBuilder->weld_container("stylisticSetsBox")) + , m_xStylisticSetsGrid(m_xBuilder->weld_container("stylisticSetsGrid")) + , m_xCharacterVariantsBox(m_xBuilder->weld_container("characterVariantsBox")) + , m_xCharacterVariantsGrid(m_xBuilder->weld_container("characterVariantsGrid")) + , m_xPreviewWindow(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWindow)) +{ + initialize(); +} + +FontFeaturesDialog::~FontFeaturesDialog() {} + +static sal_Int32 makeEnumComboBox(weld::ComboBox& rNameBox, + vcl::font::FeatureDefinition const& rFeatureDefinition, + uint32_t nDefault) +{ + sal_Int32 nRes = 0; + int count = 0; + for (vcl::font::FeatureParameter const& rParameter : rFeatureDefinition.getEnumParameters()) + { + rNameBox.append(OUString::number(rParameter.getCode()), rParameter.getDescription()); + if (rParameter.getCode() == nDefault) + nRes = count; + ++count; + } + return nRes; +} + +void FontFeaturesDialog::initialize() +{ + ScopedVclPtrInstance<VirtualDevice> aVDev(*Application::GetDefaultDevice(), + DeviceFormat::WITH_ALPHA); + std::vector<vcl::font::Feature> rFontFeatures = getFontFeatureList(m_sFontName, *aVDev); + + std::unordered_set<sal_uInt32> aDoneFeatures; + std::vector<vcl::font::Feature> rFilteredFontFeatures; + + for (vcl::font::Feature const& rFontFeature : rFontFeatures) + { + sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode; + if (!aDoneFeatures.insert(nFontFeatureCode).second) + continue; + rFilteredFontFeatures.push_back(rFontFeature); + } + + int nRowHeight = fillGrid(rFilteredFontFeatures); + + auto nFeaturesHeight = m_xContentBox->get_preferred_size().Height() + + m_xStylisticSetsBox->get_preferred_size().Height() + + m_xCharacterVariantsBox->get_preferred_size().Height(); + m_xContentWindow->set_size_request( + -1, std::min(std::max(m_xContentWindow->get_preferred_size().Height(), nFeaturesHeight), + static_cast<tools::Long>(300L))); + + if (nRowHeight) + { + // tdf#141333 use row height + the 6 px spacing of contentGrid + m_xContentWindow->vadjustment_set_step_increment(nRowHeight + 6); + } + + updateFontPreview(); +} + +int FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures) +{ + int nRowHeight(0); + + vcl::font::FeatureParser aParser(m_sFontName); + auto aExistingFeatures = aParser.getFeaturesMap(); + + sal_Int32 nIdx, nStylisticSets(0), nCharacterVariants(0), nOtherFeatures(0); + for (vcl::font::Feature const& rFontFeature : rFontFeatures) + { + sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode; + + vcl::font::FeatureDefinition aDefinition; + if (rFontFeature.m_aDefinition) + aDefinition = rFontFeature.m_aDefinition; + if (!aDefinition) + aDefinition = { nFontFeatureCode, "" }; + + if (rFontFeature.isStylisticSet()) + { + nIdx = nStylisticSets++; + m_xStylisticSetsBox->set_visible(true); + m_aFeatureItems.emplace_back( + std::make_unique<FontFeatureItem>(m_xStylisticSetsGrid.get())); + } + else if (rFontFeature.isCharacterVariant()) + { + nIdx = nCharacterVariants++; + m_xCharacterVariantsBox->set_visible(true); + m_aFeatureItems.emplace_back( + std::make_unique<FontFeatureItem>(m_xCharacterVariantsGrid.get())); + } + else + { + nIdx = nOtherFeatures++; + m_xContentBox->set_visible(true); + m_aFeatureItems.emplace_back(std::make_unique<FontFeatureItem>(m_xContentGrid.get())); + } + + int32_t nValue = 0; + if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end()) + nValue = aExistingFeatures.at(nFontFeatureCode); + else + nValue = aDefinition.getDefault(); + + FontFeatureItem& aCurrentItem = *m_aFeatureItems.back(); + aCurrentItem.m_aFeatureCode = nFontFeatureCode; + aCurrentItem.m_nDefault = aDefinition.getDefault(); + + sal_Int32 nGridPositionX = (nIdx % 2) * 2; + sal_Int32 nGridPositionY = nIdx / 2; + aCurrentItem.m_xContainer->set_grid_left_attach(nGridPositionX); + aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY); + + Link<weld::ComboBox&, void> aComboBoxSelectHandler + = LINK(this, FontFeaturesDialog, ComboBoxSelectedHdl); + Link<weld::Toggleable&, void> aCheckBoxToggleHandler + = LINK(this, FontFeaturesDialog, CheckBoxToggledHdl); + + if (aDefinition.getType() == vcl::font::FeatureParameterType::ENUM) + { + aCurrentItem.m_xText->set_label(aDefinition.getDescription()); + aCurrentItem.m_xText->show(); + + sal_Int32 nInit = makeEnumComboBox(*aCurrentItem.m_xCombo, aDefinition, nValue); + + aCurrentItem.m_xCombo->set_active(nInit); + aCurrentItem.m_xCombo->connect_changed(aComboBoxSelectHandler); + aCurrentItem.m_xCombo->show(); + } + else + { + if (nValue < 0) + { + aCurrentItem.m_xCheck->set_state(TRISTATE_INDET); + aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = true; + aCurrentItem.m_aTriStateEnabled.eState = TRISTATE_INDET; + } + else + { + aCurrentItem.m_xCheck->set_state(nValue > 0 ? TRISTATE_TRUE : TRISTATE_FALSE); + aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = false; + aCurrentItem.m_aTriStateEnabled.eState = aCurrentItem.m_xCheck->get_state(); + } + aCurrentItem.m_xCheck->set_label(aDefinition.getDescription()); + aCurrentItem.m_aToggleHdl = aCheckBoxToggleHandler; + aCurrentItem.m_xCheck->show(); + } + + nRowHeight + = std::max<int>(nRowHeight, aCurrentItem.m_xContainer->get_preferred_size().Height()); + } + + return nRowHeight; +} + +void FontFeaturesDialog::updateFontPreview() +{ + vcl::Font rPreviewFont = m_aPreviewWindow.GetFont(); + vcl::Font rPreviewFontCJK = m_aPreviewWindow.GetCJKFont(); + vcl::Font rPreviewFontCTL = m_aPreviewWindow.GetCTLFont(); + + OUString sNewFontName = createFontNameWithFeatures(); + + rPreviewFont.SetFamilyName(sNewFontName); + rPreviewFontCJK.SetFamilyName(sNewFontName); + rPreviewFontCTL.SetFamilyName(sNewFontName); + + m_aPreviewWindow.SetFont(rPreviewFont, rPreviewFontCJK, rPreviewFontCTL); +} + +IMPL_LINK(FontFeatureItem, CheckBoxToggledHdl, weld::Toggleable&, rToggle, void) +{ + m_aTriStateEnabled.ButtonToggled(rToggle); + m_aTriStateEnabled.bTriStateEnabled = false; + m_aToggleHdl.Call(rToggle); +} + +IMPL_LINK_NOARG(FontFeaturesDialog, CheckBoxToggledHdl, weld::Toggleable&, void) +{ + updateFontPreview(); +} + +IMPL_LINK_NOARG(FontFeaturesDialog, ComboBoxSelectedHdl, weld::ComboBox&, void) +{ + updateFontPreview(); +} + +OUString FontFeaturesDialog::createFontNameWithFeatures() +{ + OUString sResultFontName; + OUStringBuffer sNameSuffix; + bool bFirst = true; + + for (const auto& rEntry : m_aFeatureItems) + { + const FontFeatureItem& rItem(*rEntry); + if (rItem.m_xCheck->get_visible()) + { + if (rItem.m_xCheck->get_state() != TRISTATE_INDET) + { + if (!bFirst) + sNameSuffix.append(vcl::font::FeatureSeparator); + else + bFirst = false; + + sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode)); + if (rItem.m_xCheck->get_state() == TRISTATE_FALSE) + sNameSuffix.append("=0"); + } + } + else if (rItem.m_xCombo->get_visible() && rItem.m_xText->get_visible()) + { + sal_Int32 nSelection = rItem.m_xCombo->get_active_id().toInt32(); + if (nSelection != int(rItem.m_nDefault)) + { + if (!bFirst) + sNameSuffix.append(vcl::font::FeatureSeparator); + else + bFirst = false; + + sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode) + "=" + + OUString::number(nSelection)); + } + } + } + sResultFontName = vcl::font::trimFontNameFeatures(m_sFontName); + if (!sNameSuffix.isEmpty()) + sResultFontName += OUStringChar(vcl::font::FeaturePrefix) + sNameSuffix; + return sResultFontName; +} + +short FontFeaturesDialog::run() +{ + short nResult = GenericDialogController::run(); + if (nResult == RET_OK) + { + m_sResultFontName = createFontNameWithFeatures(); + } + return nResult; +} + +} // end svx namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |