File indexing completed on 2024-05-19 05:38:05
0001 /* 0002 SPDX-FileCopyrightText: 2020 Benjamin Port <benjamin.port@enioka.com> 0003 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "fontsaasettings.h" 0009 0010 #include <KWindowSystem> 0011 #include <QDebug> 0012 0013 using namespace Qt::StringLiterals; 0014 0015 namespace 0016 { 0017 bool defaultExclude() 0018 { 0019 return false; 0020 } 0021 0022 int defaultExcludeFrom() 0023 { 0024 return 8; 0025 } 0026 0027 int defaultExcludeTo() 0028 { 0029 return 15; 0030 } 0031 0032 bool defaultAntiAliasing() 0033 { 0034 return true; 0035 } 0036 0037 KXftConfig::SubPixel::Type defaultSubPixel() 0038 { 0039 return KXftConfig::SubPixel::Rgb; 0040 } 0041 0042 KXftConfig::Hint::Style defaultHinting() 0043 { 0044 return KXftConfig::Hint::Slight; 0045 } 0046 } 0047 0048 class FontAASettingsStore : public QObject 0049 { 0050 Q_OBJECT 0051 Q_PROPERTY(bool exclude READ exclude WRITE setExclude) 0052 Q_PROPERTY(int excludeFrom READ excludeFrom WRITE setExcludeFrom) 0053 Q_PROPERTY(int excludeTo READ excludeTo WRITE setExcludeTo) 0054 Q_PROPERTY(bool antiAliasing READ antiAliasing WRITE setAntiAliasing) 0055 Q_PROPERTY(KXftConfig::SubPixel::Type subPixel READ subPixel WRITE setSubPixel) 0056 Q_PROPERTY(KXftConfig::Hint::Style hinting READ hinting WRITE setHinting) 0057 public: 0058 FontAASettingsStore(FontsAASettings *parent = nullptr) 0059 : QObject(parent) 0060 { 0061 load(); 0062 } 0063 0064 bool exclude() const 0065 { 0066 return m_exclude; 0067 } 0068 0069 void setExclude(bool exclude) 0070 { 0071 if (m_exclude != exclude) { 0072 m_exclude = exclude; 0073 } 0074 } 0075 0076 int excludeFrom() const 0077 { 0078 return m_excludeFrom; 0079 } 0080 0081 void setExcludeFrom(int excludeFrom) 0082 { 0083 if (m_excludeFrom != excludeFrom) { 0084 m_excludeFrom = excludeFrom; 0085 } 0086 } 0087 0088 int excludeTo() const 0089 { 0090 return m_excludeTo; 0091 } 0092 0093 void setExcludeTo(int excludeTo) 0094 { 0095 if (m_excludeTo != excludeTo) { 0096 m_excludeTo = excludeTo; 0097 } 0098 } 0099 0100 bool isImmutable() const 0101 { 0102 return m_isImmutable; 0103 } 0104 0105 bool antiAliasing() const 0106 { 0107 return m_antiAliasing; 0108 } 0109 0110 void setAntiAliasing(bool antiAliasing) 0111 { 0112 if (antiAliasing != m_antiAliasing) { 0113 m_antiAliasingChanged = true; 0114 m_antiAliasing = antiAliasing; 0115 } 0116 } 0117 0118 KXftConfig::SubPixel::Type subPixel() const 0119 { 0120 return m_subPixel; 0121 } 0122 0123 void setSubPixel(KXftConfig::SubPixel::Type subPixel) 0124 { 0125 if (m_subPixel != subPixel) { 0126 m_subPixelChanged = true; 0127 m_subPixel = subPixel; 0128 } 0129 } 0130 0131 KXftConfig::Hint::Style hinting() const 0132 { 0133 return m_hinting; 0134 } 0135 0136 void setHinting(KXftConfig::Hint::Style hinting) 0137 { 0138 if (m_hinting != hinting) { 0139 m_hintingChanged = true; 0140 m_hinting = hinting; 0141 } 0142 } 0143 0144 void save() 0145 { 0146 KXftConfig xft; 0147 KXftConfig::AntiAliasing::State aaState = KXftConfig::AntiAliasing::NotSet; 0148 if (m_antiAliasingChanged || xft.antiAliasingHasLocalConfig()) { 0149 aaState = m_antiAliasing ? KXftConfig::AntiAliasing::Enabled : KXftConfig::AntiAliasing::Disabled; 0150 } 0151 xft.setAntiAliasing(aaState); 0152 0153 if (m_exclude) { 0154 xft.setExcludeRange(m_excludeFrom, m_excludeTo); 0155 } else { 0156 xft.setExcludeRange(0, 0); 0157 } 0158 0159 if (m_subPixelChanged || xft.subPixelTypeHasLocalConfig()) { 0160 xft.setSubPixelType(m_subPixel); 0161 } else { 0162 xft.setSubPixelType(KXftConfig::SubPixel::NotSet); 0163 } 0164 0165 if (m_hintingChanged || xft.hintStyleHasLocalConfig()) { 0166 xft.setHintStyle(m_hinting); 0167 } else { 0168 xft.setHintStyle(KXftConfig::Hint::NotSet); 0169 } 0170 0171 // Write to KConfig to sync with krdb 0172 KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); 0173 KConfigGroup grp(config, u"General"_s); 0174 0175 grp.writeEntry("XftSubPixel", KXftConfig::toStr(m_subPixel)); 0176 0177 if (aaState == KXftConfig::AntiAliasing::NotSet) { 0178 grp.revertToDefault("XftAntialias"); 0179 } else { 0180 grp.writeEntry("XftAntialias", aaState == KXftConfig::AntiAliasing::Enabled); 0181 } 0182 0183 QString hs(KXftConfig::toStr(m_hinting)); 0184 if (hs != grp.readEntry("XftHintStyle")) { 0185 if (KXftConfig::Hint::NotSet == m_hinting) { 0186 grp.revertToDefault("XftHintStyle"); 0187 } else { 0188 grp.writeEntry("XftHintStyle", hs); 0189 } 0190 } 0191 0192 xft.apply(); 0193 0194 m_subPixelChanged = false; 0195 m_hintingChanged = false; 0196 m_antiAliasingChanged = false; 0197 } 0198 0199 void load() 0200 { 0201 double from, to; 0202 KXftConfig xft; 0203 0204 if (xft.getExcludeRange(from, to)) { 0205 setExclude(true); 0206 setExcludeFrom(from); 0207 setExcludeTo(to); 0208 } else { 0209 setExclude(defaultExclude()); 0210 setExcludeFrom(defaultExcludeFrom()); 0211 setExcludeTo(defaultExcludeTo()); 0212 } 0213 0214 // sub pixel 0215 KXftConfig::SubPixel::Type spType = KXftConfig::SubPixel::NotSet; 0216 xft.getSubPixelType(spType); 0217 // if it is not set, we have no subpixel hinting 0218 if (spType == KXftConfig::SubPixel::NotSet) { 0219 spType = KXftConfig::SubPixel::None; 0220 } 0221 setSubPixel(spType); 0222 0223 // hinting 0224 KXftConfig::Hint::Style hStyle = KXftConfig::Hint::NotSet; 0225 xft.getHintStyle(hStyle); 0226 // if it is not set, we have no hinting 0227 if (hStyle == KXftConfig::Hint::NotSet) { 0228 hStyle = KXftConfig::Hint::None; 0229 } 0230 setHinting(hStyle); 0231 0232 KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); 0233 KConfigGroup cg(config, QStringLiteral("General")); 0234 m_isImmutable = cg.isEntryImmutable("XftAntialias"); 0235 0236 const auto aaState = xft.getAntiAliasing(); 0237 setAntiAliasing(aaState != KXftConfig::AntiAliasing::Disabled); 0238 0239 m_subPixelChanged = false; 0240 m_hintingChanged = false; 0241 m_antiAliasingChanged = false; 0242 } 0243 0244 private: 0245 bool m_isImmutable; 0246 bool m_antiAliasing; 0247 bool m_antiAliasingChanged; 0248 KXftConfig::SubPixel::Type m_subPixel; 0249 bool m_subPixelChanged; 0250 KXftConfig::Hint::Style m_hinting; 0251 bool m_hintingChanged; 0252 bool m_exclude; 0253 int m_excludeFrom; 0254 int m_excludeTo; 0255 }; 0256 0257 FontsAASettings::FontsAASettings(QObject *parent) 0258 : FontsAASettingsBase(parent) 0259 , m_fontAASettingsStore(new FontAASettingsStore(this)) 0260 { 0261 addItemInternal("exclude", defaultExclude(), &FontsAASettings::excludeChanged); 0262 addItemInternal("excludeFrom", defaultExcludeFrom(), &FontsAASettings::excludeFromChanged); 0263 addItemInternal("excludeTo", defaultExcludeTo(), &FontsAASettings::excludeToChanged); 0264 addItemInternal("antiAliasing", defaultAntiAliasing(), &FontsAASettings::antiAliasingChanged); 0265 addItemInternal("subPixel", defaultSubPixel(), &FontsAASettings::subPixelChanged); 0266 addItemInternal("hinting", defaultHinting(), &FontsAASettings::hintingChanged); 0267 0268 connect(this, &FontsAASettings::forceFontDPIChanged, this, &FontsAASettings::dpiChanged); 0269 } 0270 0271 void FontsAASettings::addItemInternal(const QByteArray &propertyName, const QVariant &defaultValue, NotifySignalType notifySignal) 0272 { 0273 auto item = new KPropertySkeletonItem(m_fontAASettingsStore, propertyName, defaultValue); 0274 addItem(item, propertyName); 0275 item->setNotifyFunction([this, notifySignal] { 0276 Q_EMIT(this->*notifySignal)(); 0277 }); 0278 } 0279 0280 bool FontsAASettings::exclude() const 0281 { 0282 return findItem("exclude")->property().toBool(); 0283 } 0284 0285 void FontsAASettings::setExclude(bool exclude) 0286 { 0287 findItem("exclude")->setProperty(exclude); 0288 } 0289 0290 int FontsAASettings::excludeFrom() const 0291 { 0292 return findItem("excludeFrom")->property().toInt(); 0293 } 0294 0295 void FontsAASettings::setExcludeFrom(int excludeFrom) 0296 { 0297 findItem("excludeFrom")->setProperty(excludeFrom); 0298 } 0299 0300 int FontsAASettings::excludeTo() const 0301 { 0302 return findItem("excludeTo")->property().toInt(); 0303 } 0304 0305 void FontsAASettings::setExcludeTo(int excludeTo) 0306 { 0307 findItem("excludeTo")->setProperty(excludeTo); 0308 } 0309 0310 bool FontsAASettings::antiAliasing() const 0311 { 0312 return findItem("antiAliasing")->property().toBool(); 0313 } 0314 0315 void FontsAASettings::setAntiAliasing(bool enabled) 0316 { 0317 if (antiAliasing() == enabled) { 0318 return; 0319 } 0320 0321 findItem("antiAliasing")->setProperty(enabled); 0322 if (!enabled) { 0323 setSubPixel(KXftConfig::SubPixel::None); 0324 } else if (subPixel() == KXftConfig::SubPixel::None) { 0325 setSubPixel(defaultSubPixel()); 0326 } 0327 } 0328 0329 int FontsAASettings::dpi() const 0330 { 0331 return forceFontDPI(); 0332 } 0333 0334 void FontsAASettings::setDpi(int newDPI) 0335 { 0336 if (dpi() == newDPI) { 0337 return; 0338 } 0339 0340 setForceFontDPI(newDPI); 0341 Q_EMIT dpiChanged(); 0342 } 0343 0344 KXftConfig::SubPixel::Type FontsAASettings::subPixel() const 0345 { 0346 return findItem("subPixel")->property().value<KXftConfig::SubPixel::Type>(); 0347 } 0348 0349 void FontsAASettings::setSubPixel(KXftConfig::SubPixel::Type type) 0350 { 0351 if (subPixel() == type) { 0352 return; 0353 } 0354 0355 findItem("subPixel")->setProperty(type); 0356 } 0357 0358 KXftConfig::Hint::Style FontsAASettings::hinting() const 0359 { 0360 return findItem("hinting")->property().value<KXftConfig::Hint::Style>(); 0361 } 0362 0363 bool FontsAASettings::isAaImmutable() const 0364 { 0365 return m_fontAASettingsStore->isImmutable(); 0366 } 0367 0368 bool FontsAASettings::excludeStateProxy() const 0369 { 0370 return false; 0371 } 0372 0373 void FontsAASettings::setHinting(KXftConfig::Hint::Style hinting) 0374 { 0375 findItem("hinting")->setProperty(hinting); 0376 } 0377 0378 bool FontsAASettings::usrSave() 0379 { 0380 m_fontAASettingsStore->save(); 0381 return FontsAASettingsBase::usrSave(); 0382 } 0383 0384 #include "fontsaasettings.moc"