Use QtConcurrentRun to initialize FontConfig in a separate thread.

master
Torsten Paul 2014-12-21 03:46:13 +01:00
parent abdf80c494
commit 98a9ea7e12
4 changed files with 60 additions and 28 deletions

View File

@ -127,7 +127,7 @@ mingw* {
}
CONFIG += qt
QT += opengl
QT += opengl concurrent
# see http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
# and https://github.com/openscad/openscad/pull/119

View File

@ -81,11 +81,20 @@ const std::string &FontInfo::get_file() const
}
FontCache * FontCache::self = NULL;
FontCache::ProgressHandlerFunc *FontCache::start_cb = NULL;
FontCache::ProgressHandlerFunc *FontCache::end_cb = NULL;
FontCache::InitHandlerFunc *FontCache::cb_handler = FontCache::defaultInitHandler;
void *FontCache::cb_userdata = NULL;
const std::string FontCache::DEFAULT_FONT("XXX");
/**
* Default implementation for the font cache initialization. In case no other
* handler is registered, the cache build is just called synchronously in the
* current thread by this handler.
*/
void FontCache::defaultInitHandler(FontCacheInitializer *initializer, void *)
{
initializer->run();
}
FontCache::FontCache()
{
this->init_ok = false;
@ -134,9 +143,8 @@ FontCache::FontCache()
}
}
if (FontCache::start_cb) FontCache::start_cb(FontCache::cb_userdata);
FcConfigBuildFonts(this->config);
if (FontCache::end_cb) FontCache::end_cb(FontCache::cb_userdata);
FontCacheInitializer initializer(this->config);
cb_handler(&initializer, cb_userdata);
// For use by LibraryInfo
FcStrList *dirs = FcConfigGetFontDirs(this->config);
@ -166,10 +174,9 @@ FontCache * FontCache::instance()
return self;
}
void FontCache::registerProgressHandler(ProgressHandlerFunc *start, ProgressHandlerFunc *end, void *userdata)
void FontCache::registerProgressHandler(InitHandlerFunc *handler, void *userdata)
{
FontCache::start_cb = start;
FontCache::end_cb = end;
FontCache::cb_handler = handler;
FontCache::cb_userdata = userdata;
}

View File

@ -59,6 +59,19 @@ private:
typedef std::vector<FontInfo> FontInfoList;
/**
* Slow call of the font cache initialization. This is separated here so it
* can be passed to the GUI to run in a separate thread while showing a
* progress dialog.
*/
class FontCacheInitializer {
public:
FontCacheInitializer(FcConfig *config) : config(config) { }
void run() { FcConfigBuildFonts(config); }
private:
FcConfig *config;
};
class FontCache {
public:
const static std::string DEFAULT_FONT;
@ -76,17 +89,19 @@ public:
static FontCache *instance();
typedef void (ProgressHandlerFunc)(void *userdata);
static void registerProgressHandler(ProgressHandlerFunc *start, ProgressHandlerFunc *end, void *userdata = NULL);
typedef void (InitHandlerFunc)(FontCacheInitializer *initializer, void *userdata);
static void registerProgressHandler(InitHandlerFunc *handler, void *userdata = NULL);
private:
typedef std::pair<FT_Face, time_t> cache_entry_t;
typedef std::map<std::string, cache_entry_t> cache_t;
static FontCache *self;
static ProgressHandlerFunc *start_cb;
static ProgressHandlerFunc *end_cb;
static void *cb_userdata;
static InitHandlerFunc *cb_handler;
static void *cb_userdata;
static void defaultInitHandler(FontCacheInitializer *delegate, void *userdata);
bool init_ok;
cache_t cache;
FcConfig *config;

View File

@ -549,6 +549,9 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#include <QFileInfo>
#include <QMetaType>
#include <QTextCodec>
#include <QProgressDialog>
#include <QFutureWatcher>
#include <QtConcurrentRun>
Q_DECLARE_METATYPE(shared_ptr<const Geometry>);
@ -578,20 +581,29 @@ bool QtUseGUI()
return useGUI;
}
#include <QProgressDialog>
QProgressDialog *fontCacheProgress = NULL;
void fontCacheStart(void *userdata)
void dialogThreadFunc(FontCacheInitializer *initializer)
{
fontCacheProgress = new QProgressDialog("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.", QString(), 0, 0);
fontCacheProgress->show();
initializer->run();
}
void fontCacheEnd(void *userdata)
void dialogInitHandler(FontCacheInitializer *initializer, void *)
{
delete fontCacheProgress;
fontCacheProgress = NULL;
QProgressDialog dialog;
dialog.setLabelText("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.");
dialog.setCancelButton(0);
QFutureWatcher<void> futureWatcher;
QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
QFuture<void> future = QtConcurrent::run(boost::bind(dialogThreadFunc, initializer));
futureWatcher.setFuture(future);
dialog.exec();
futureWatcher.waitForFinished();
}
int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
@ -624,9 +636,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha
const QString &app_path = app.applicationDirPath();
PlatformUtils::registerApplicationPath(app_path.toLocal8Bit().constData());
FontCache::registerProgressHandler(fontCacheStart, fontCacheEnd);
FontCache::registerProgressHandler(dialogInitHandler);
parser_init();