#include "fgqcanvasfontcache.h" #include #include #include #include #include #include #include FGQCanvasFontCache::FGQCanvasFontCache(QNetworkAccessManager* nam, QObject *parent) : QObject(parent) , m_downloader(nam) { } QFont FGQCanvasFontCache::fontForName(QByteArray name, bool* ok) { if (m_cache.contains(name)) { if (ok) { *ok = true; } return m_cache.value(name); // easy! } lookupFile(name); if (m_cache.contains(name)) { if (ok) { *ok = true; } return m_cache.value(name); } if (ok) { *ok = false; } return QFont(); // default font } static FGQCanvasFontCache* s_instance = nullptr; void FGQCanvasFontCache::initialise(QNetworkAccessManager *nam) { Q_ASSERT(s_instance == nullptr); s_instance = new FGQCanvasFontCache(nam); } FGQCanvasFontCache *FGQCanvasFontCache::instance() { return s_instance; } void FGQCanvasFontCache::setHost(QString hostName, int portNumber) { m_hostName = hostName; m_port = portNumber; } void FGQCanvasFontCache::onFontDownloadFinished() { QByteArray fontPath = sender()->property("font").toByteArray(); qDebug() << "finished download of " << fontPath; QDir cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); QString absPath = cacheDir.absoluteFilePath(fontPath); QFileInfo finfo(fontPath); cacheDir.mkpath(finfo.dir().path()); QFile f(absPath); if (!f.open(QIODevice::WriteOnly)) { qWarning() << "failed to open cache file" << f.fileName(); } QNetworkReply* reply = qobject_cast(sender()); Q_ASSERT(m_transfers.contains(reply)); f.write(reply->readAll()); f.close(); m_transfers.removeOne(reply); // call ourselves again now it's cached; lookupFile(fontPath); } void FGQCanvasFontCache::onFontDownloadError(QNetworkReply::NetworkError) { QNetworkReply* reply = qobject_cast(sender()); qWarning() << "font download failed:" << reply->errorString(); } void FGQCanvasFontCache::lookupFile(QByteArray name) { QString path = QStandardPaths::locate(QStandardPaths::CacheLocation, name); if (path.isEmpty()) { QUrl url; url.setScheme("http"); url.setHost(m_hostName); url.setPort(m_port); url.setPath("/Fonts/" + name); Q_FOREACH (QNetworkReply* transfer, m_transfers) { if (transfer->url() == url) { return; // transfer already active } } qDebug() << "reqeusting font" << url; QNetworkReply* reply = m_downloader->get(QNetworkRequest(url)); reply->setProperty("font", name); connect(reply, &QNetworkReply::finished, this, &FGQCanvasFontCache::onFontDownloadFinished); // connect(reply, &QNetworkReply::error, this, &FGQCanvasFontCache::onFontDownloadError); m_transfers.append(reply); } else { qDebug() << "found font" << name << "at path" << path; int fontFamilyId = QFontDatabase::addApplicationFont(path); QStringList families = QFontDatabase::applicationFontFamilies(fontFamilyId); qDebug() << "families are:" << families; // compute a QFont and cache QFont font(families.front()); m_cache.insert(name, font); } }