Krita Source Code Documentation
Loading...
Searching...
No Matches
FontAxesModel.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6#include "FontAxesModel.h"
7#include <klocalizedstring.h>
8#include <QDebug>
10#include <KisResourceModel.h>
11#include <KoFontRegistry.h>
13
14const QString WEIGHT_TAG = "wght";
15const QString WIDTH_TAG = "wdth";
16const QString SLANT_TAG = "slnt";
17const QString ITALIC_TAG = "ital";
18const QString OPTICAL_TAG = "opsz";
19
29
31 : QAbstractItemModel(parent)
32 , d(new Private)
33{
35 QList<QLocale> locales;
36 Q_FOREACH (const QString langCode, KLocalizedString::languages()) {
37 locales.append(QLocale(langCode));
38 }
39 d->locales = locales;
40}
41
45
47{
49 for (int i=0; i < axes.size(); i++) {
50 QString tag = axes.at(i).tag;
51 if (!(tag == WEIGHT_TAG
52 || tag == WIDTH_TAG
53 || tag == ITALIC_TAG
54 || tag == SLANT_TAG)
55 && !axes.at(i).axisHidden) {
56 newAxes.append(axes.at(i));
57 }
58 }
59 if (newAxes != d->axes) {
60 // TODO: Rework this whole thing so we don't update axes unless absolutely necessary.
61 // This wll probably require a filterproxy model where invisible axes are filtered out.
62 beginResetModel();
63 d->axes = newAxes;
64 endResetModel();
65 }
66}
67
69{
70 d->opticalSizeDisabled = disable;
71}
72
74{
75 d->blockAxesValuesUpdate = block;
76}
77
79{
80 return d->blockAxesValuesUpdate;
81}
82
83QModelIndex FontAxesModel::index(int row, int column, const QModelIndex &parent) const
84{
85 Q_UNUSED(parent);
86 if (column != 0) return QModelIndex();
87 if (row >= 0 && row < d->axes.size()) return createIndex(row, column, &row);
88 return QModelIndex();
89}
90
91QModelIndex FontAxesModel::parent(const QModelIndex &child) const
92{
93 Q_UNUSED(child);
94 return QModelIndex();
95}
96
97int FontAxesModel::rowCount(const QModelIndex &parent) const
98{
99 Q_UNUSED(parent);
100 return d->axes.size();
101}
102
103int FontAxesModel::columnCount(const QModelIndex &parent) const
104{
105 Q_UNUSED(parent);
106 return 1;
107}
108
109QVariant FontAxesModel::data(const QModelIndex &index, int role) const
110{
111 if (!index.isValid()) return QVariant();
112
113 KoSvgText::FontFamilyAxis axis = d->axes.at(index.row());
114 if (role == Qt::DisplayRole) {
115 if (axis.tag == OPTICAL_TAG){
116 // Refers to https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_opsz
117 return i18nc("@info:label", "Optical Size");
118 }
119 if (axis.localizedLabels.isEmpty()) {
120 return axis.tag;
121 }
122 QString label = axis.localizedLabels.value(QLocale(QLocale::English), axis.localizedLabels.values().first());
123 Q_FOREACH(const QLocale &locale, d->locales) {
124 if (axis.localizedLabels.keys().contains(locale)) {
125 label = axis.localizedLabels.value(locale, label);
126 break;
127 }
128 }
129 return label;
130 } else if (role == Qt::EditRole) {
131 return d->axisValues.value(axis.tag, axis.defaultValue).toDouble();
132 } else if (role == Min) {
133 return axis.min;
134 } else if (role == Max) {
135 return axis.max;
136 } else if (role == Hidden) {
137 return axis.axisHidden;
138 }
139 return QVariant();
140}
141
142bool FontAxesModel::setData(const QModelIndex &index, const QVariant &value, int role)
143{
144 if (index.isValid() && role == Qt::EditRole) {
145
146 KoSvgText::FontFamilyAxis axis = d->axes.at(index.row());
147 if (!d->axisValues.keys().contains(axis.tag) || !qFuzzyCompare(d->axisValues.value(axis.tag).toDouble(), value.toDouble())) {
148 d->axisValues.insert(axis.tag, value);
149 if (!d->blockAxesValuesUpdate) {
150 emit axisValuesChanged();
151 }
152 emit dataChanged(index, index, { Qt::EditRole});
153 return true;
154 }
155 }
156 return false;
157}
158
159Qt::ItemFlags FontAxesModel::flags(const QModelIndex &index) const
160{
161 Qt::ItemFlags flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsEditable;
162
163 /*KoSvgText::FontFamilyAxis axis = d->axes.value(index.row());
164 if (!(axis.tag == OPTICAL_TAG && d->opticalSizeDisabled)) {
165 flags |= Qt::ItemIsEnabled;
166 }*/
167
168 return flags;
169}
170
171QHash<int, QByteArray> FontAxesModel::roleNames() const
172{
173 QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
174 roles[Min] = "axismin";
175 roles[Max] = "axismax";
176 roles[Hidden] = "axishidden";
177 return roles;
178}
179
180QVariantMap FontAxesModel::axisValues() const
181{
182 return d->axisValues;
183}
184
186{
187 QStringList families = textPropertiesModel->fontFamilies();
189
190
191 if (!families.isEmpty() && d->fontModel) {
192
193 std::optional<QString> name = KoFontRegistry::instance()->wwsNameByFamilyName(families.first());
194 QString familyName = !name? families.first(): name.value();
195
196 QVector<KoResourceSP> res = d->fontModel->resourcesForFilename(familyName);
197 if (!res.isEmpty()) {
198 KoFontFamilySP family = res.first().staticCast<KoFontFamily>();
199 if (family) {
200 axes = family->axes();
201 }
202 }
203 }
205 setAxesData(axes);
206 setAxisValues(textPropertiesModel->axisValues());
208}
209
210void FontAxesModel::setAxisValues(const QVariantMap &newAxisValues)
211{
212 if (d->axisValues == newAxisValues)
213 return;
214 d->axisValues = newAxisValues;
215
216 if (!d->blockAxesValuesUpdate) {
217 emit axisValuesChanged();
218 }
219
220 QModelIndex idx1 = index(0, 0, QModelIndex());
221 QModelIndex idx2 = index(rowCount(QModelIndex())-1, 0, QModelIndex());
222 if (idx1.isValid() && idx2.isValid()) {
223 emit dataChanged(idx1, idx2, {Qt::EditRole});
224 }
225}
const QString SLANT_TAG
const QString WEIGHT_TAG
const QString ITALIC_TAG
const QString WIDTH_TAG
const QString OPTICAL_TAG
float value(const T *src, size_t ch)
const QString SLANT_TAG
const QString WEIGHT_TAG
const QString ITALIC_TAG
const QString WIDTH_TAG
const QString OPTICAL_TAG
void setAxisValues(const QVariantMap &newAxisValues)
void setAxesData(QList< KoSvgText::FontFamilyAxis > axes)
QVariant data(const QModelIndex &index, int role) const override
QModelIndex parent(const QModelIndex &child) const override
void axisValuesChanged()
@ Min
double, represents lower end
@ Max
double, represents upper end
QHash< int, QByteArray > roleNames() const override
QModelIndex index(int row, int column, const QModelIndex &parent) const override
bool axesValueSignalBlocked() const
Qt::ItemFlags flags(const QModelIndex &index) const override
FontAxesModel(QObject *parent=nullptr)
QVariantMap axisValues
int rowCount(const QModelIndex &parent) const override
void setBlockAxesValuesSignal(bool block)
Q_INVOKABLE void setFromTextPropertiesModel(KoSvgTextPropertiesModel *textPropertiesModel)
int columnCount(const QModelIndex &parent) const override
void setOpticalSizeDisabled(bool disable)
If optical size link is enabled, then the slider should be disabled.
const QScopedPointer< Private > d
bool setData(const QModelIndex &index, const QVariant &value, int role) override
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
The KoFontFamily class Abstract representation of a Weight/Width/Slant font family,...
std::optional< QString > wwsNameByFamilyName(const QString familyName) const
static KoFontRegistry * instance()
The KoSvgTextPropertiesModel class.
const QString FontFamilies
KisResourceModel * fontModel
QList< QLocale > locales
QList< KoSvgText::FontFamilyAxis > axes
QHash< QLocale, QString > localizedLabels
Definition KoSvgText.h:777