File indexing completed on 2025-02-02 04:11:27
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "font_delegate.hpp" 0008 0009 #include <QPainter> 0010 0011 using namespace glaxnimate::gui; 0012 using namespace glaxnimate; 0013 0014 static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script) 0015 { 0016 switch (script) { 0017 case QLocale::ArabicScript: 0018 return QFontDatabase::Arabic; 0019 case QLocale::CyrillicScript: 0020 return QFontDatabase::Cyrillic; 0021 case QLocale::GurmukhiScript: 0022 return QFontDatabase::Gurmukhi; 0023 case QLocale::SimplifiedHanScript: 0024 return QFontDatabase::SimplifiedChinese; 0025 case QLocale::TraditionalHanScript: 0026 return QFontDatabase::TraditionalChinese; 0027 case QLocale::LatinScript: 0028 return QFontDatabase::Latin; 0029 case QLocale::ArmenianScript: 0030 return QFontDatabase::Armenian; 0031 case QLocale::BengaliScript: 0032 return QFontDatabase::Bengali; 0033 case QLocale::DevanagariScript: 0034 return QFontDatabase::Devanagari; 0035 case QLocale::GeorgianScript: 0036 return QFontDatabase::Georgian; 0037 case QLocale::GreekScript: 0038 return QFontDatabase::Greek; 0039 case QLocale::GujaratiScript: 0040 return QFontDatabase::Gujarati; 0041 case QLocale::HebrewScript: 0042 return QFontDatabase::Hebrew; 0043 case QLocale::JapaneseScript: 0044 return QFontDatabase::Japanese; 0045 case QLocale::KhmerScript: 0046 return QFontDatabase::Khmer; 0047 case QLocale::KannadaScript: 0048 return QFontDatabase::Kannada; 0049 case QLocale::KoreanScript: 0050 return QFontDatabase::Korean; 0051 case QLocale::LaoScript: 0052 return QFontDatabase::Lao; 0053 case QLocale::MalayalamScript: 0054 return QFontDatabase::Malayalam; 0055 case QLocale::MyanmarScript: 0056 return QFontDatabase::Myanmar; 0057 case QLocale::TamilScript: 0058 return QFontDatabase::Tamil; 0059 case QLocale::TeluguScript: 0060 return QFontDatabase::Telugu; 0061 case QLocale::ThaanaScript: 0062 return QFontDatabase::Thaana; 0063 case QLocale::ThaiScript: 0064 return QFontDatabase::Thai; 0065 case QLocale::TibetanScript: 0066 return QFontDatabase::Tibetan; 0067 case QLocale::SinhalaScript: 0068 return QFontDatabase::Sinhala; 0069 case QLocale::SyriacScript: 0070 return QFontDatabase::Syriac; 0071 case QLocale::OriyaScript: 0072 return QFontDatabase::Oriya; 0073 case QLocale::OghamScript: 0074 return QFontDatabase::Ogham; 0075 case QLocale::RunicScript: 0076 return QFontDatabase::Runic; 0077 case QLocale::NkoScript: 0078 return QFontDatabase::Nko; 0079 default: 0080 return QFontDatabase::Any; 0081 } 0082 } 0083 static QFontDatabase::WritingSystem writingSystemFromLocale() 0084 { 0085 QStringList uiLanguages = QLocale::system().uiLanguages(); 0086 QLocale::Script script; 0087 if (!uiLanguages.isEmpty()) 0088 script = QLocale(uiLanguages.at(0)).script(); 0089 else 0090 script = QLocale::system().script(); 0091 0092 return writingSystemFromScript(script); 0093 } 0094 0095 static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin) 0096 { 0097 #if QT_VERSION_MAJOR < 6 0098 QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase().writingSystems(font.family()); 0099 #else 0100 QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase::writingSystems(font.family()); 0101 #endif 0102 0103 // this just confuses the algorithm below. Vietnamese is Latin with lots of special chars 0104 writingSystems.removeOne(QFontDatabase::Vietnamese); 0105 *hasLatin = writingSystems.removeOne(QFontDatabase::Latin); 0106 0107 if (writingSystems.isEmpty()) 0108 return QFontDatabase::Any; 0109 0110 QFontDatabase::WritingSystem system = writingSystemFromLocale(); 0111 0112 if (writingSystems.contains(system)) 0113 return system; 0114 0115 if (system == QFontDatabase::TraditionalChinese 0116 && writingSystems.contains(QFontDatabase::SimplifiedChinese)) { 0117 return QFontDatabase::SimplifiedChinese; 0118 } 0119 0120 if (system == QFontDatabase::SimplifiedChinese 0121 && writingSystems.contains(QFontDatabase::TraditionalChinese)) { 0122 return QFontDatabase::TraditionalChinese; 0123 } 0124 0125 system = writingSystems.constLast(); 0126 0127 if (!*hasLatin) { 0128 // we need to show something 0129 return system; 0130 } 0131 0132 if (writingSystems.count() == 1 && system > QFontDatabase::Cyrillic) 0133 return system; 0134 0135 if (writingSystems.count() <= 2 && system > QFontDatabase::Armenian && system < QFontDatabase::Vietnamese) 0136 return system; 0137 0138 if (writingSystems.count() <= 5 && system >= QFontDatabase::SimplifiedChinese && system <= QFontDatabase::Korean) 0139 return system; 0140 0141 return QFontDatabase::Any; 0142 } 0143 0144 0145 0146 font::FontDelegate::FontDelegate(QObject *parent) 0147 : QAbstractItemDelegate(parent), 0148 // truetype(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fonttruetype-16.png")), 0149 // bitmap(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fontbitmap-16.png")), 0150 writingSystem(QFontDatabase::Any) 0151 { 0152 } 0153 0154 0155 void font::FontDelegate::paint(QPainter *painter, 0156 const QStyleOptionViewItem &option, 0157 const QModelIndex &index) const 0158 { 0159 QString text = index.data(Qt::DisplayRole).toString(); 0160 QFont font(option.font); 0161 font.setPointSize(QFontInfo(font).pointSize() * 3 / 2); 0162 QFont font2 = font; 0163 font2.setFamily(text); 0164 0165 bool hasLatin; 0166 QFontDatabase::WritingSystem system = writingSystemForFont(font2, &hasLatin); 0167 if (hasLatin) 0168 font = font2; 0169 0170 QRect r = option.rect; 0171 0172 if (option.state & QStyle::State_Selected) { 0173 painter->save(); 0174 painter->setBrush(option.palette.highlight()); 0175 painter->setPen(Qt::NoPen); 0176 painter->drawRect(option.rect); 0177 painter->setPen(QPen(option.palette.highlightedText(), 0)); 0178 } 0179 0180 /* 0181 const QIcon *icon = &bitmap; 0182 if (QFontDatabase().isSmoothlyScalable(text)) { 0183 icon = &truetype; 0184 } 0185 const QSize actualSize = icon->actualSize(r.size()); 0186 const QRect iconRect = QStyle::alignedRect(option.direction, option.displayAlignment, 0187 actualSize, r); 0188 icon->paint(painter, iconRect, Qt::AlignLeft|Qt::AlignVCenter); 0189 if (option.direction == Qt::RightToLeft) 0190 r.setRight(r.right() - actualSize.width() - 4); 0191 else 0192 r.setLeft(r.left() + actualSize.width() + 4); 0193 */ 0194 QFont old = painter->font(); 0195 painter->setFont(font); 0196 0197 const Qt::Alignment textAlign = QStyle::visualAlignment(option.direction, option.displayAlignment); 0198 // If the ascent of the font is larger than the height of the rect, 0199 // we will clip the text, so it's better to align the tight bounding rect in this case 0200 // This is specifically for fonts where the ascent is very large compared to 0201 // the descent, like certain of the Stix family. 0202 QFontMetricsF fontMetrics(font); 0203 if (fontMetrics.ascent() > r.height()) { 0204 QRectF tbr = fontMetrics.tightBoundingRect(text); 0205 QRect textRect(r); 0206 textRect.setHeight(textRect.height() + (r.height() - tbr.height())); 0207 painter->drawText(textRect, Qt::AlignBottom|Qt::TextSingleLine|textAlign, text); 0208 } else { 0209 painter->drawText(r, Qt::AlignVCenter|Qt::TextSingleLine|textAlign, text); 0210 } 0211 0212 if (writingSystem != QFontDatabase::Any) 0213 system = writingSystem; 0214 0215 if (system != QFontDatabase::Any) { 0216 int w = painter->fontMetrics().horizontalAdvance(text + QLatin1String(" ")); 0217 painter->setFont(font2); 0218 0219 #if QT_VERSION_MAJOR < 6 0220 QString sample = QFontDatabase().writingSystemSample(system); 0221 #else 0222 QString sample = QFontDatabase::writingSystemSample(system); 0223 #endif 0224 if (option.direction == Qt::RightToLeft) 0225 r.setRight(r.right() - w); 0226 else 0227 r.setLeft(r.left() + w); 0228 painter->drawText(r, Qt::AlignVCenter|Qt::TextSingleLine|textAlign, sample); 0229 } 0230 painter->setFont(old); 0231 0232 if (option.state & QStyle::State_Selected) 0233 painter->restore(); 0234 0235 } 0236 0237 QSize font::FontDelegate::sizeHint(const QStyleOptionViewItem &option, 0238 const QModelIndex &index) const 0239 { 0240 QString text = index.data(Qt::DisplayRole).toString(); 0241 QFont font(option.font); 0242 // font.setFamily(text); 0243 font.setPointSize(QFontInfo(font).pointSize() * 3/2); 0244 QFontMetrics fontMetrics(font); 0245 return QSize(fontMetrics.horizontalAdvance(text), fontMetrics.height()); 0246 }