Remote-canvas loads fonts from the host.
This commit is contained in:
parent
34ca0c15cc
commit
066d81568d
6 changed files with 195 additions and 2 deletions
|
@ -30,6 +30,8 @@ set(SOURCES
|
|||
fgcanvaswidget.h
|
||||
canvastreemodel.cpp
|
||||
canvastreemodel.h
|
||||
fgqcanvasfontcache.cpp
|
||||
fgqcanvasfontcache.h
|
||||
)
|
||||
|
||||
qt5_wrap_ui(uic_sources temporarywidget.ui)
|
||||
|
|
|
@ -5,11 +5,16 @@
|
|||
|
||||
#include "fgcanvaspaintcontext.h"
|
||||
#include "localprop.h"
|
||||
#include "fgqcanvasfontcache.h"
|
||||
|
||||
FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
|
||||
FGCanvasElement(pr, prop),
|
||||
_metrics(QFont())
|
||||
{
|
||||
// this signal fires infrequently enough, it's simpler just to have
|
||||
// all texts watch it.
|
||||
connect(FGQCanvasFontCache::instance(), &FGQCanvasFontCache::fontLoaded,
|
||||
this, &FGCanvasText::onFontLoaded);
|
||||
}
|
||||
|
||||
void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
|
||||
|
@ -131,10 +136,25 @@ void FGCanvasText::markFontDirty()
|
|||
_fontDirty = true;
|
||||
}
|
||||
|
||||
void FGCanvasText::onFontLoaded(QByteArray name)
|
||||
{
|
||||
QByteArray fontName = getCascadedStyle("font", QString()).toByteArray();
|
||||
if (name != fontName) {
|
||||
return; // not our font
|
||||
}
|
||||
|
||||
markFontDirty();
|
||||
}
|
||||
|
||||
void FGCanvasText::rebuildFont() const
|
||||
{
|
||||
QString fontName = getCascadedStyle("font", QString()).toString();
|
||||
QFont f(fontName);
|
||||
QByteArray fontName = getCascadedStyle("font", QString()).toByteArray();
|
||||
bool ok;
|
||||
QFont f = FGQCanvasFontCache::instance()->fontForName(fontName, &ok);
|
||||
if (!ok) {
|
||||
// wait for the correct font
|
||||
}
|
||||
|
||||
f.setPixelSize(getCascadedStyle("character-size", 16).toInt());
|
||||
_font = f;
|
||||
_metrics = QFontMetricsF(_font);
|
||||
|
|
|
@ -24,6 +24,8 @@ private:
|
|||
void setDrawMode(QVariant var);
|
||||
|
||||
void markFontDirty();
|
||||
|
||||
void onFontLoaded(QByteArray name);
|
||||
private:
|
||||
void rebuildFont() const;
|
||||
void rebuildAlignment(QVariant var) const;
|
||||
|
|
122
utils/fgqcanvas/fgqcanvasfontcache.cpp
Normal file
122
utils/fgqcanvas/fgqcanvasfontcache.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include "fgqcanvasfontcache.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QStandardPaths>
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
#include <QNetworkReply>
|
||||
#include <QFontDatabase>
|
||||
#include <QFile>
|
||||
|
||||
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::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<QNetworkReply*>(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<QNetworkReply*>(sender());
|
||||
qWarning() << "font download failed:" << reply->errorString();
|
||||
}
|
||||
|
||||
void FGQCanvasFontCache::lookupFile(QByteArray name)
|
||||
{
|
||||
QString path = QStandardPaths::locate(QStandardPaths::CacheLocation, name);
|
||||
if (path.isEmpty()) {
|
||||
QUrl url = QUrl("http://localhost:8080/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);
|
||||
}
|
||||
}
|
||||
|
||||
|
39
utils/fgqcanvas/fgqcanvasfontcache.h
Normal file
39
utils/fgqcanvas/fgqcanvasfontcache.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef FGQCANVASFONTCACHE_H
|
||||
#define FGQCANVASFONTCACHE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFont>
|
||||
#include <QDir>
|
||||
#include <QHash>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
class FGQCanvasFontCache : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FGQCanvasFontCache(QNetworkAccessManager* nam, QObject *parent = 0);
|
||||
|
||||
QFont fontForName(QByteArray name, bool* ok = nullptr);
|
||||
|
||||
static void initialise(QNetworkAccessManager* nam);
|
||||
static FGQCanvasFontCache* instance();
|
||||
|
||||
signals:
|
||||
void fontLoaded(QByteArray name);
|
||||
|
||||
private slots:
|
||||
void onFontDownloadFinished();
|
||||
void onFontDownloadError(QNetworkReply::NetworkError);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager* m_downloader;
|
||||
QHash<QByteArray, QFont> m_cache;
|
||||
|
||||
void lookupFile(QByteArray name);
|
||||
|
||||
QList<QNetworkReply*> m_transfers;
|
||||
};
|
||||
|
||||
#endif // FGQCANVASFONTCACHE_H
|
|
@ -1,5 +1,9 @@
|
|||
#include "temporarywidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "fgqcanvasfontcache.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -9,6 +13,10 @@ int main(int argc, char *argv[])
|
|||
a.setOrganizationDomain("flightgear.org");
|
||||
a.setOrganizationName("FlightGear");
|
||||
|
||||
QNetworkAccessManager* downloader = new QNetworkAccessManager;
|
||||
|
||||
FGQCanvasFontCache::initialise(downloader);
|
||||
|
||||
TemporaryWidget w;
|
||||
w.show();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue