QmlDesigner: Refactor font collector

Fixes: QDS-3643
Change-Id: Iacc26eb0d0cbaad9d9242b548588f3afa3eba2ac
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2021-01-29 18:15:33 +02:00
parent 5b582e042b
commit 384cc3c022

View File

@@ -56,43 +56,44 @@ QByteArray fileToByteArray(QString const &filename)
return {}; return {};
} }
} // namespace // Returns font id or -1 in case of failure
static int resolveFont(const QString &fontFile, QFont &outFont)
void ImageCacheFontCollector::start(Utils::SmallStringView name,
Utils::SmallStringView,
const ImageCache::AuxiliaryData &auxiliaryDataValue,
CaptureCallback captureCallback,
AbortCallback abortCallback)
{ {
auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizeAuxiliaryData>(auxiliaryDataValue); int fontId = -1;
QColor textColor = auxiliaryData.colorName; QByteArray fontData(fileToByteArray(fontFile));
QSize size = auxiliaryData.size;
QRect rect({0, 0}, size);
QByteArray fontData(fileToByteArray(QString(name)));
if (!fontData.isEmpty()) { if (!fontData.isEmpty()) {
int fontId = QFontDatabase::addApplicationFontFromData(fontData); fontId = QFontDatabase::addApplicationFontFromData(fontData);
if (fontId != -1) { if (fontId != -1) {
QRawFont rawFont(fontData, 10.); // Pixel size is irrelevant, we only need style/weight QRawFont rawFont(fontData, 10.); // Pixel size is irrelevant, we only need style/weight
const QStringList families = QFontDatabase::applicationFontFamilies(fontId); const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
if (!families.isEmpty()) { if (!families.isEmpty()) {
QString fontFamily = families.first(); QString fontFamily = families.first();
QString text = fontFamily + "\n\n" + auxiliaryData.text; outFont.setFamily(fontFamily);
QFont font(fontFamily); outFont.setStyle(rawFont.style());
font.setStyle(rawFont.style()); outFont.setStyleName(rawFont.styleName());
font.setStyleName(rawFont.styleName());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
font.setWeight(QFont::Weight(rawFont.weight())); outFont.setWeight(QFont::Weight(rawFont.weight()));
#else #else
font.setWeight(rawFont.weight()); outFont.setWeight(rawFont.weight());
#endif #endif
}
}
}
return fontId;
}
static QImage createFontImage(const QString &text, const QColor &textColor, const QFont &font,
const QSize &size)
{
QRect rect({0, 0}, size);
QImage image(size, QImage::Format_ARGB32); QImage image(size, QImage::Format_ARGB32);
image.fill(Qt::transparent); image.fill(Qt::transparent);
int pixelSize(200); int pixelSize(200);
int flags = Qt::AlignCenter; int flags = Qt::AlignCenter;
QFont renderFont = font;
while (pixelSize >= 2) { while (pixelSize >= 2) {
font.setPixelSize(pixelSize); renderFont.setPixelSize(pixelSize);
QFontMetrics fm(font, &image); QFontMetrics fm(renderFont, &image);
QRect bounds = fm.boundingRect(rect, flags, text); QRect bounds = fm.boundingRect(rect, flags, text);
if (bounds.width() < rect.width() && bounds.height() < rect.height()) { if (bounds.width() < rect.width() && bounds.height() < rect.height()) {
break; break;
@@ -111,14 +112,33 @@ void ImageCacheFontCollector::start(Utils::SmallStringView name,
QPainter painter(&image); QPainter painter(&image);
painter.setPen(textColor); painter.setPen(textColor);
painter.setFont(font); painter.setFont(renderFont);
painter.drawText(rect, flags, text); painter.drawText(rect, flags, text);
return image;
}
} // namespace
void ImageCacheFontCollector::start(Utils::SmallStringView name,
Utils::SmallStringView,
const ImageCache::AuxiliaryData &auxiliaryDataValue,
CaptureCallback captureCallback,
AbortCallback abortCallback)
{
QFont font;
if (int fontId = resolveFont(QString(name), font) >= 0) {
auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizeAuxiliaryData>(auxiliaryDataValue);
QColor textColor = auxiliaryData.colorName;
QSize size = auxiliaryData.size;
QString text = font.family() + "\n\n" + auxiliaryData.text;
QImage image = createFontImage(text, textColor, font, size);
if (!image.isNull()) {
captureCallback(std::move(image), {}); captureCallback(std::move(image), {});
return; return;
} }
QFontDatabase::removeApplicationFont(fontId);
}
} }
abortCallback(); abortCallback();
} }
@@ -128,63 +148,18 @@ std::pair<QImage, QImage> ImageCacheFontCollector::createImage(
Utils::SmallStringView, Utils::SmallStringView,
const ImageCache::AuxiliaryData &auxiliaryDataValue) const ImageCache::AuxiliaryData &auxiliaryDataValue)
{ {
QFont font;
if (int fontId = resolveFont(QString(name), font) >= 0) {
auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizeAuxiliaryData>(auxiliaryDataValue); auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizeAuxiliaryData>(auxiliaryDataValue);
QColor textColor = auxiliaryData.colorName; QColor textColor = auxiliaryData.colorName;
QSize size = auxiliaryData.size; QSize size = auxiliaryData.size;
QRect rect({0, 0}, size); QString text = font.family() + "\n\n" + auxiliaryData.text;
QByteArray fontData(fileToByteArray(QString(name))); QImage image = createFontImage(text, textColor, font, size);
if (!fontData.isEmpty()) {
int fontId = QFontDatabase::addApplicationFontFromData(fontData);
if (fontId != -1) {
QRawFont rawFont(fontData, 10.); // Pixel size is irrelevant, we only need style/weight
const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
if (!families.isEmpty()) {
QString fontFamily = families.first();
QString text = fontFamily + "\n\n" + auxiliaryData.text;
QFont font(fontFamily);
font.setStyle(rawFont.style());
font.setStyleName(rawFont.styleName());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
font.setWeight(QFont::Weight(rawFont.weight()));
#else
font.setWeight(rawFont.weight());
#endif
QImage image(size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
int pixelSize(200);
int flags = Qt::AlignCenter;
while (pixelSize >= 2) {
font.setPixelSize(pixelSize);
QFontMetrics fm(font, &image);
QRect bounds = fm.boundingRect(rect, flags, text);
if (bounds.width() < rect.width() && bounds.height() < rect.height()) {
break;
} else {
int newPixelSize = pixelSize - 1;
if (bounds.width() >= rect.width())
newPixelSize = int(qreal(pixelSize) * qreal(rect.width())
/ qreal(bounds.width()));
else if (bounds.height() >= rect.height())
newPixelSize = int(qreal(pixelSize) * qreal(rect.height())
/ qreal(bounds.height()));
if (newPixelSize < pixelSize)
pixelSize = newPixelSize;
else
--pixelSize;
}
}
QPainter painter(&image);
painter.setPen(textColor);
painter.setFont(font);
painter.drawText(rect, flags, text);
if (!image.isNull())
return {image, {}}; return {image, {}};
} }
QFontDatabase::removeApplicationFont(fontId);
}
}
return {}; return {};
} }
@@ -193,67 +168,19 @@ QIcon ImageCacheFontCollector::createIcon(Utils::SmallStringView name,
Utils::SmallStringView, Utils::SmallStringView,
const ImageCache::AuxiliaryData &auxiliaryDataValue) const ImageCache::AuxiliaryData &auxiliaryDataValue)
{ {
auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizesAuxiliaryData>(auxiliaryDataValue);
QColor textColor = auxiliaryData.colorName;
auto sizes = auxiliaryData.sizes;
QIcon icon; QIcon icon;
QByteArray fontData(fileToByteArray(QString(name))); QFont font;
if (!fontData.isEmpty()) { if (int fontId = resolveFont(QString(name), font) >= 0) {
int fontId = QFontDatabase::addApplicationFontFromData(fontData); auto &&auxiliaryData = Utils::get<ImageCache::FontCollectorSizesAuxiliaryData>(auxiliaryDataValue);
if (fontId != -1) { QColor textColor = auxiliaryData.colorName;
QRawFont rawFont(fontData, 10.); // Pixel size is irrelevant, we only need style/weight const auto sizes = auxiliaryData.sizes;
const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
if (!families.isEmpty()) {
QString fontFamily = families.first();
QString text = auxiliaryData.text; QString text = auxiliaryData.text;
QFont font(fontFamily);
font.setStyle(rawFont.style());
font.setStyleName(rawFont.styleName());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
font.setWeight(QFont::Weight(rawFont.weight()));
#else
font.setWeight(rawFont.weight());
#endif
for (QSize size : sizes) { for (QSize size : sizes) {
QPixmap pixmap(size); QImage image = createFontImage(text, textColor, font, size);
pixmap.fill(Qt::transparent); if (!image.isNull())
int pixelSize(200); icon.addPixmap(QPixmap::fromImage(image));
int flags = Qt::AlignCenter;
QRect rect({0, 0}, size);
while (pixelSize >= 2) {
font.setPixelSize(pixelSize);
QFontMetrics fm(font, &pixmap);
QRect bounds = fm.boundingRect(rect, flags, text);
if (bounds.width() < rect.width() && bounds.height() < rect.height()) {
break;
} else {
int newPixelSize = pixelSize - 1;
if (bounds.width() >= rect.width())
newPixelSize = int(qreal(pixelSize) * qreal(rect.width())
/ qreal(bounds.width()));
else if (bounds.height() >= rect.height())
newPixelSize = int(qreal(pixelSize) * qreal(rect.height())
/ qreal(bounds.height()));
if (newPixelSize < pixelSize)
pixelSize = newPixelSize;
else
--pixelSize;
}
}
QPainter painter(&pixmap);
painter.setPen(textColor);
painter.setFont(font);
painter.drawText(rect, flags, text);
icon.addPixmap(pixmap);
}
} else {
QFontDatabase::removeApplicationFont(fontId);
}
} }
} }