1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "distancefieldmodel.h"
5#include "distancefieldmodelworker.h"
6
7#include <QThread>
8#include <QMetaEnum>
9
10QT_BEGIN_NAMESPACE
11
12DistanceFieldModel::DistanceFieldModel(QObject *parent)
13 : QAbstractListModel(parent)
14 , m_glyphCount(0)
15{
16 int index = metaObject()->indexOfEnumerator(name: "UnicodeRange");
17 Q_ASSERT(index >= 0);
18
19 m_rangeEnum = metaObject()->enumerator(index);
20
21 m_workerThread.reset(other: new QThread);
22
23 m_worker = new DistanceFieldModelWorker;
24 m_worker->moveToThread(thread: m_workerThread.data());
25 connect(sender: m_workerThread.data(), signal: &QThread::finished,
26 context: m_worker, slot: &QObject::deleteLater);
27
28 connect(sender: m_worker, signal: &DistanceFieldModelWorker::fontLoaded,
29 context: this, slot: &DistanceFieldModel::startGeneration);
30 connect(sender: m_worker, signal: &DistanceFieldModelWorker::fontLoaded,
31 context: this, slot: &DistanceFieldModel::reserveSpace);
32 connect(sender: m_worker, signal: &DistanceFieldModelWorker::distanceFieldGenerated,
33 context: this, slot: &DistanceFieldModel::addDistanceField);
34 connect(sender: m_worker, signal: &DistanceFieldModelWorker::fontGenerated,
35 context: this, slot: &DistanceFieldModel::stopGeneration);
36 connect(sender: m_worker, signal: &DistanceFieldModelWorker::distanceFieldGenerated,
37 context: this, slot: &DistanceFieldModel::distanceFieldGenerated);
38 connect(sender: m_worker, signal: &DistanceFieldModelWorker::error,
39 context: this, slot: &DistanceFieldModel::error);
40
41 m_workerThread->start();
42}
43
44DistanceFieldModel::~DistanceFieldModel()
45{
46 m_workerThread->quit();
47 m_workerThread->wait();
48}
49
50QVariant DistanceFieldModel::headerData(int section, Qt::Orientation orientation, int role) const
51{
52 Q_UNUSED(section);
53 Q_UNUSED(orientation);
54 Q_UNUSED(role);
55 return QVariant();
56}
57
58int DistanceFieldModel::rowCount(const QModelIndex &parent) const
59{
60 if (parent.isValid())
61 return 0;
62 else
63 return m_glyphCount;
64}
65
66QVariant DistanceFieldModel::data(const QModelIndex &index, int role) const
67{
68 static QPixmap defaultImage;
69 if (defaultImage.isNull()) {
70 defaultImage = QPixmap(64, 64);
71 defaultImage.fill(fillColor: Qt::white);
72 }
73
74 if (!index.isValid())
75 return QVariant();
76
77 if (role == Qt::DecorationRole) {
78 if (index.row() < m_distanceFields.size()) {
79 return QPixmap::fromImage(image: m_distanceFields.at(i: index.row()).scaled(w: 64, h: 64));
80 } else {
81 return defaultImage;
82 }
83
84 }
85
86 return QVariant();
87}
88
89void DistanceFieldModel::setFont(const QString &fileName)
90{
91 QMetaObject::invokeMethod(object: m_worker,
92 function: [this, fileName] { m_worker->loadFont(fileName); },
93 type: Qt::QueuedConnection);
94}
95
96void DistanceFieldModel::reserveSpace(quint16 glyphCount,
97 bool doubleResolution,
98 qreal pixelSize)
99{
100 beginResetModel();
101 m_glyphsPerUnicodeRange.clear();
102 m_distanceFields.clear();
103 m_glyphCount = glyphCount;
104 if (glyphCount > 0)
105 m_distanceFields.reserve(asize: glyphCount);
106 endResetModel();
107
108 m_doubleGlyphResolution = doubleResolution;
109 m_pixelSize = pixelSize;
110
111 QMetaObject::invokeMethod(object: m_worker,
112 function: [this] { m_worker->generateOneDistanceField(); },
113 type: Qt::QueuedConnection);
114}
115
116DistanceFieldModel::UnicodeRange DistanceFieldModel::unicodeRangeForUcs4(quint32 ucs4) const
117{
118 int index = metaObject()->indexOfEnumerator(name: "UnicodeRange");
119 Q_ASSERT(index >= 0);
120
121 QMetaEnum range = metaObject()->enumerator(index);
122 for (int i = 0; i < range.keyCount() - 1; ++i) {
123 int rangeStart = range.value(index: i);
124 int rangeEnd = range.value(index: i + 1);
125 if (quint32(rangeStart) <= ucs4 && quint32(rangeEnd) >= ucs4)
126 return UnicodeRange(rangeStart);
127 }
128
129 return Other;
130}
131
132QList<DistanceFieldModel::UnicodeRange> DistanceFieldModel::unicodeRanges() const
133{
134 return m_glyphsPerUnicodeRange.uniqueKeys();
135}
136
137QList<glyph_t> DistanceFieldModel::glyphIndexesForUnicodeRange(UnicodeRange range) const
138{
139 return m_glyphsPerUnicodeRange.values(key: range);
140}
141
142QString DistanceFieldModel::nameForUnicodeRange(UnicodeRange range) const
143{
144 return QString::fromLatin1(ba: m_rangeEnum.valueToKey(value: int(range)));
145}
146
147void DistanceFieldModel::addDistanceField(const QImage &distanceField,
148 const QPainterPath &path,
149 glyph_t glyphId,
150 quint32 ucs4)
151{
152 if (glyphId >= quint16(m_distanceFields.size()))
153 m_distanceFields.resize(size: glyphId + 1);
154 m_distanceFields[glyphId] = distanceField;
155 if (glyphId >= quint16(m_paths.size()))
156 m_paths.resize(size: glyphId + 1);
157 m_paths[glyphId] = path;
158
159 if (ucs4 != 0) {
160 UnicodeRange range = unicodeRangeForUcs4(ucs4);
161 m_glyphsPerUnicodeRange.insert(key: range, value: glyphId);
162 m_glyphsPerUcs4.insert(key: ucs4, value: glyphId);
163 }
164
165 emit dataChanged(topLeft: createIndex(arow: glyphId, acolumn: 0), bottomRight: createIndex(arow: glyphId, acolumn: 0));
166
167 QMetaObject::invokeMethod(object: m_worker,
168 function: [this] { m_worker->generateOneDistanceField(); },
169 type: Qt::QueuedConnection);
170}
171
172glyph_t DistanceFieldModel::glyphIndexForUcs4(quint32 ucs4) const
173{
174 return m_glyphsPerUcs4.value(key: ucs4);
175}
176
177QT_END_NAMESPACE
178

source code of qttools/src/distancefieldgenerator/distancefieldmodel.cpp