mirror of https://github.com/vitalif/openscad
Use QtConcurrentRun to initialize FontConfig in a separate thread.
parent
abdf80c494
commit
98a9ea7e12
|
@ -127,7 +127,7 @@ mingw* {
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG += qt
|
CONFIG += qt
|
||||||
QT += opengl
|
QT += opengl concurrent
|
||||||
|
|
||||||
# see http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
|
# see http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
|
||||||
# and https://github.com/openscad/openscad/pull/119
|
# and https://github.com/openscad/openscad/pull/119
|
||||||
|
|
|
@ -81,11 +81,20 @@ const std::string &FontInfo::get_file() const
|
||||||
}
|
}
|
||||||
|
|
||||||
FontCache * FontCache::self = NULL;
|
FontCache * FontCache::self = NULL;
|
||||||
FontCache::ProgressHandlerFunc *FontCache::start_cb = NULL;
|
FontCache::InitHandlerFunc *FontCache::cb_handler = FontCache::defaultInitHandler;
|
||||||
FontCache::ProgressHandlerFunc *FontCache::end_cb = NULL;
|
|
||||||
void *FontCache::cb_userdata = NULL;
|
void *FontCache::cb_userdata = NULL;
|
||||||
const std::string FontCache::DEFAULT_FONT("XXX");
|
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()
|
FontCache::FontCache()
|
||||||
{
|
{
|
||||||
this->init_ok = false;
|
this->init_ok = false;
|
||||||
|
@ -134,9 +143,8 @@ FontCache::FontCache()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FontCache::start_cb) FontCache::start_cb(FontCache::cb_userdata);
|
FontCacheInitializer initializer(this->config);
|
||||||
FcConfigBuildFonts(this->config);
|
cb_handler(&initializer, cb_userdata);
|
||||||
if (FontCache::end_cb) FontCache::end_cb(FontCache::cb_userdata);
|
|
||||||
|
|
||||||
// For use by LibraryInfo
|
// For use by LibraryInfo
|
||||||
FcStrList *dirs = FcConfigGetFontDirs(this->config);
|
FcStrList *dirs = FcConfigGetFontDirs(this->config);
|
||||||
|
@ -166,10 +174,9 @@ FontCache * FontCache::instance()
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontCache::registerProgressHandler(ProgressHandlerFunc *start, ProgressHandlerFunc *end, void *userdata)
|
void FontCache::registerProgressHandler(InitHandlerFunc *handler, void *userdata)
|
||||||
{
|
{
|
||||||
FontCache::start_cb = start;
|
FontCache::cb_handler = handler;
|
||||||
FontCache::end_cb = end;
|
|
||||||
FontCache::cb_userdata = userdata;
|
FontCache::cb_userdata = userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,19 @@ private:
|
||||||
|
|
||||||
typedef std::vector<FontInfo> FontInfoList;
|
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 {
|
class FontCache {
|
||||||
public:
|
public:
|
||||||
const static std::string DEFAULT_FONT;
|
const static std::string DEFAULT_FONT;
|
||||||
|
@ -76,17 +89,19 @@ public:
|
||||||
|
|
||||||
static FontCache *instance();
|
static FontCache *instance();
|
||||||
|
|
||||||
typedef void (ProgressHandlerFunc)(void *userdata);
|
typedef void (InitHandlerFunc)(FontCacheInitializer *initializer, void *userdata);
|
||||||
static void registerProgressHandler(ProgressHandlerFunc *start, ProgressHandlerFunc *end, void *userdata = NULL);
|
static void registerProgressHandler(InitHandlerFunc *handler, void *userdata = NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::pair<FT_Face, time_t> cache_entry_t;
|
typedef std::pair<FT_Face, time_t> cache_entry_t;
|
||||||
typedef std::map<std::string, cache_entry_t> cache_t;
|
typedef std::map<std::string, cache_entry_t> cache_t;
|
||||||
|
|
||||||
static FontCache *self;
|
static FontCache *self;
|
||||||
static ProgressHandlerFunc *start_cb;
|
static InitHandlerFunc *cb_handler;
|
||||||
static ProgressHandlerFunc *end_cb;
|
static void *cb_userdata;
|
||||||
static void *cb_userdata;
|
|
||||||
|
static void defaultInitHandler(FontCacheInitializer *delegate, void *userdata);
|
||||||
|
|
||||||
bool init_ok;
|
bool init_ok;
|
||||||
cache_t cache;
|
cache_t cache;
|
||||||
FcConfig *config;
|
FcConfig *config;
|
||||||
|
|
|
@ -549,6 +549,9 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(shared_ptr<const Geometry>);
|
Q_DECLARE_METATYPE(shared_ptr<const Geometry>);
|
||||||
|
|
||||||
|
@ -578,20 +581,29 @@ bool QtUseGUI()
|
||||||
return useGUI;
|
return useGUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dialogThreadFunc(FontCacheInitializer *initializer)
|
||||||
#include <QProgressDialog>
|
|
||||||
QProgressDialog *fontCacheProgress = NULL;
|
|
||||||
|
|
||||||
void fontCacheStart(void *userdata)
|
|
||||||
{
|
{
|
||||||
fontCacheProgress = new QProgressDialog("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.", QString(), 0, 0);
|
initializer->run();
|
||||||
fontCacheProgress->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fontCacheEnd(void *userdata)
|
void dialogInitHandler(FontCacheInitializer *initializer, void *)
|
||||||
{
|
{
|
||||||
delete fontCacheProgress;
|
QProgressDialog dialog;
|
||||||
fontCacheProgress = NULL;
|
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)
|
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();
|
const QString &app_path = app.applicationDirPath();
|
||||||
PlatformUtils::registerApplicationPath(app_path.toLocal8Bit().constData());
|
PlatformUtils::registerApplicationPath(app_path.toLocal8Bit().constData());
|
||||||
|
|
||||||
FontCache::registerProgressHandler(fontCacheStart, fontCacheEnd);
|
FontCache::registerProgressHandler(dialogInitHandler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
parser_init();
|
parser_init();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue