Gut splash screen; add notice to use metaforce-gui

This commit is contained in:
Luke Street 2021-05-22 23:25:27 -04:00
parent f1a1796cdb
commit 5e3f70eb77
5 changed files with 21 additions and 306 deletions

View File

@ -5,7 +5,7 @@
namespace metaforce { namespace metaforce {
#define SPLASH_WIDTH 555 #define SPLASH_WIDTH 555
#define SPLASH_HEIGHT 300 #define SPLASH_HEIGHT 100
#define WIRE_START 0 #define WIRE_START 0
#define WIRE_FRAMES 60 #define WIRE_FRAMES 60
@ -17,22 +17,11 @@ namespace metaforce {
#define LINE_WIDTH 2 #define LINE_WIDTH 2
#define TEXT_MARGIN 10 #define TEXT_MARGIN 10
#define BADGE_WIDTH 551
#define BADGE_HEIGHT 217
#define BADGE_MARGIN 35
SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res) SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res)
: ModalWindow(res, vm.rootView(), : ModalWindow(res, vm.rootView(),
specter::RectangleConstraint(SPLASH_WIDTH * res.pixelFactor(), SPLASH_HEIGHT * res.pixelFactor())) specter::RectangleConstraint(SPLASH_WIDTH * res.pixelFactor(), SPLASH_HEIGHT * res.pixelFactor()))
, m_vm(vm) , m_vm(vm)
, m_textColor(res.themeData().uiText()) , m_textColor(res.themeData().uiText()) {
, m_textColorClear(m_textColor)
, m_newString(m_vm.translate<locale::new_project>())
, m_openString(m_vm.translate<locale::open_project>())
, m_extractString(m_vm.translate<locale::extract_game>())
, m_newProjBind(*this)
, m_openProjBind(*this)
, m_extractProjBind(*this) {
if (METAFORCE_WC_DATE[0] != '\0' && METAFORCE_WC_REVISION[0] != '\0' && METAFORCE_WC_BRANCH[0] != '\0') { if (METAFORCE_WC_DATE[0] != '\0' && METAFORCE_WC_REVISION[0] != '\0' && METAFORCE_WC_BRANCH[0] != '\0') {
m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"), m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"),
vm.translate<locale::version>(), METAFORCE_WC_DESCRIBE, vm.translate<locale::version>(), METAFORCE_WC_DESCRIBE,
@ -40,38 +29,15 @@ SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res)
vm.translate<locale::commit>(), METAFORCE_WC_REVISION/*, vm.translate<locale::commit>(), METAFORCE_WC_REVISION/*,
vm.translate<locale::date>(), METAFORCE_WC_DATE*/); vm.translate<locale::date>(), METAFORCE_WC_DATE*/);
} }
m_openProjBind.m_openRecentMenuRoot.m_text = vm.translate<locale::recent_projects>();
m_textColorClear[3] = 0.0;
} }
void SplashScreen::think() { void SplashScreen::think() {
if (phase() == Phase::Done) { if (phase() == Phase::Done) {
if (m_fileBrowser.m_view)
m_fileBrowser.m_view.reset();
return; return;
} }
OPTICK_EVENT(); OPTICK_EVENT();
ModalWindow::think(); ModalWindow::think();
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->think();
if (m_openButt.m_view)
m_openButt.m_view->think();
if (m_newProjBind.m_deferPath.size()) {
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Making project '{}'")), m_newProjBind.m_deferPath);
m_vm.projectManager().newProject(m_newProjBind.m_deferPath);
m_newProjBind.m_deferPath.clear();
} else if (m_openProjBind.m_deferPath.size()) {
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Opening project '{}'")), m_openProjBind.m_deferPath);
m_vm.projectManager().openProject(m_openProjBind.m_deferPath);
m_openProjBind.m_deferPath.clear();
} else if (m_extractProjBind.m_deferPath.size()) {
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Extracting game '{}'")), m_extractProjBind.m_deferPath);
m_vm.projectManager().extractGame(m_extractProjBind.m_deferPath);
m_extractProjBind.m_deferPath.clear();
}
} }
void SplashScreen::updateContentOpacity(float opacity) { void SplashScreen::updateContentOpacity(float opacity) {
@ -81,21 +47,16 @@ void SplashScreen::updateContentOpacity(float opacity) {
m_title.reset(new specter::TextView(res, *this, res.m_titleFont)); m_title.reset(new specter::TextView(res, *this, res.m_titleFont));
zeus::CColor clearColor = res.themeData().uiText(); zeus::CColor clearColor = res.themeData().uiText();
clearColor[3] = 0.0; clearColor[3] = 0.0;
m_title->typesetGlyphs("URDE", clearColor); m_title->typesetGlyphs("Metaforce", clearColor);
m_buildInfo.reset(new specter::MultiLineTextView(res, *this, res.m_mainFont, specter::TextView::Alignment::Right)); m_buildInfo.reset(new specter::MultiLineTextView(res, *this, res.m_mainFont, specter::TextView::Alignment::Right));
m_buildInfo->typesetGlyphs(m_buildInfoStr, clearColor); m_buildInfo->typesetGlyphs(m_buildInfoStr, clearColor);
m_badgeIcon.reset(new specter::IconView(res, *this, GetBadge())); m_badgeText.reset(new specter::TextView(res, *this, res.m_heading18));
m_badgeText.reset(new specter::TextView(res, *this, res.m_heading18, specter::TextView::Alignment::Right));
m_badgeText->typesetGlyphs(BADGE_PHRASE, clearColor); m_badgeText->typesetGlyphs(BADGE_PHRASE, clearColor);
m_newButt.m_view.reset( m_infoStr = std::make_unique<specter::TextView>(res, *this, res.m_mainFont);
new specter::Button(res, *this, &m_newProjBind, m_newString, nullptr, specter::Button::Style::Text)); m_infoStr->typesetGlyphs("No game detected. Use metaforce-gui or check README for command-line options."sv, clearColor);
m_openButt.m_view.reset(
new specter::Button(res, *this, &m_openProjBind, m_openString, nullptr, specter::Button::Style::Text));
m_extractButt.m_view.reset(
new specter::Button(res, *this, &m_extractProjBind, m_extractString, nullptr, specter::Button::Style::Text));
updateSize(); updateSize();
} }
@ -105,97 +66,8 @@ void SplashScreen::updateContentOpacity(float opacity) {
zeus::CColor color = zeus::CColor::lerp(clearColor, res.themeData().uiText(), opacity); zeus::CColor color = zeus::CColor::lerp(clearColor, res.themeData().uiText(), opacity);
m_title->colorGlyphs(color); m_title->colorGlyphs(color);
m_buildInfo->colorGlyphs(color); m_buildInfo->colorGlyphs(color);
m_badgeIcon->setMultiplyColor({1.f, 1.f, 1.f, color.a()});
m_badgeText->colorGlyphs(color); m_badgeText->colorGlyphs(color);
m_newButt.m_view->colorGlyphs(color); m_infoStr->colorGlyphs(color);
m_openButt.m_view->colorGlyphs(color);
m_extractButt.m_view->colorGlyphs(color);
}
void SplashScreen::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (skipBuildInAnimation())
return;
if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed())
m_fileBrowser.m_view->mouseDown(coord, button, mod);
else {
m_newButt.mouseDown(coord, button, mod);
m_openButt.mouseDown(coord, button, mod);
m_extractButt.mouseDown(coord, button, mod);
}
}
void SplashScreen::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed())
m_fileBrowser.m_view->mouseUp(coord, button, mod);
else {
m_newButt.mouseUp(coord, button, mod);
m_openButt.mouseUp(coord, button, mod);
m_extractButt.mouseUp(coord, button, mod);
}
}
void SplashScreen::mouseMove(const boo::SWindowCoord& coord) {
if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed())
m_fileBrowser.m_view->mouseMove(coord);
else {
m_newButt.mouseMove(coord);
m_openButt.mouseMove(coord);
m_extractButt.mouseMove(coord);
}
}
void SplashScreen::mouseEnter(const boo::SWindowCoord& coord) {
if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed())
m_fileBrowser.m_view->mouseEnter(coord);
else {
m_newButt.mouseEnter(coord);
m_openButt.mouseEnter(coord);
m_extractButt.mouseEnter(coord);
}
}
void SplashScreen::mouseLeave(const boo::SWindowCoord& coord) {
if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed())
m_fileBrowser.m_view->mouseLeave(coord);
else {
m_newButt.mouseLeave(coord);
m_openButt.mouseLeave(coord);
m_extractButt.mouseLeave(coord);
}
}
void SplashScreen::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->scroll(coord, scroll);
}
void SplashScreen::touchDown(const boo::STouchCoord& coord, uintptr_t tid) {
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->touchDown(coord, tid);
}
void SplashScreen::touchUp(const boo::STouchCoord& coord, uintptr_t tid) {
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->touchUp(coord, tid);
}
void SplashScreen::touchMove(const boo::STouchCoord& coord, uintptr_t tid) {
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->touchMove(coord, tid);
}
void SplashScreen::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
if (skipBuildInAnimation())
return;
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->charKeyDown(charCode, mods, isRepeat);
}
void SplashScreen::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
if (skipBuildInAnimation())
return;
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->specialKeyDown(key, mods, isRepeat);
} }
void SplashScreen::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { void SplashScreen::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
@ -206,48 +78,25 @@ void SplashScreen::resized(const boo::SWindowRect& root, const boo::SWindowRect&
centerRect.location[0] = root.size[0] / 2 - (SPLASH_WIDTH * pf / 2.0); centerRect.location[0] = root.size[0] / 2 - (SPLASH_WIDTH * pf / 2.0);
centerRect.location[1] = root.size[1] / 2 - (SPLASH_HEIGHT * pf / 2.0); centerRect.location[1] = root.size[1] / 2 - (SPLASH_HEIGHT * pf / 2.0);
boo::SWindowRect badgeRect = centerRect;
badgeRect.location[0] += LINE_WIDTH * pf;
badgeRect.location[1] += BADGE_MARGIN * pf;
badgeRect.size[0] = BADGE_WIDTH * pf;
badgeRect.size[1] = BADGE_HEIGHT * pf;
boo::SWindowRect textRect = centerRect; boo::SWindowRect textRect = centerRect;
textRect.location[0] += TEXT_MARGIN * pf; textRect.location[0] += TEXT_MARGIN * pf;
textRect.location[1] += (SPLASH_HEIGHT - 36) * pf; textRect.location[1] += (SPLASH_HEIGHT - 28) * pf;
if (m_title) { if (m_title) {
m_title->resized(root, textRect); m_title->resized(root, textRect);
textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf;
textRect.location[1] -= 5 * pf;
m_buildInfo->resized(root, textRect);
textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf; textRect.location[1] -= m_title->nominalHeight() * 0.75;
textRect.location[1] = centerRect.location[1] + (BADGE_MARGIN + TEXT_MARGIN) * pf;
m_badgeIcon->resized(root, badgeRect);
m_badgeText->resized(root, textRect); m_badgeText->resized(root, textRect);
textRect.size[0] = m_newButt.m_view->nominalWidth(); textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf;
textRect.size[1] = m_newButt.m_view->nominalHeight(); textRect.location[1] = centerRect.location[1] + (SPLASH_HEIGHT - 36) * pf - 5 * pf;
textRect.location[1] = centerRect.location[1] + 20 * pf; m_buildInfo->resized(root, textRect);
textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH / 4 * pf - m_newButt.m_view->nominalWidth() / 2;
m_newButt.m_view->resized(root, textRect);
textRect.size[0] = m_openButt.m_view->nominalWidth(); textRect.size[0] = m_infoStr->nominalWidth();
textRect.size[1] = m_openButt.m_view->nominalHeight(); textRect.size[1] = m_infoStr->nominalHeight();
textRect.location[1] = centerRect.location[1] + 20 * pf; textRect.location[1] = centerRect.location[1] + 20 * pf;
textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH * 2 / 4 * pf - m_openButt.m_view->nominalWidth() / 2; textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH * 2 / 4 * pf - m_infoStr->nominalWidth() / 2;
m_openButt.m_view->resized(root, textRect); m_infoStr->resized(root, textRect);
textRect.size[0] = m_extractButt.m_view->nominalWidth();
textRect.size[1] = m_extractButt.m_view->nominalHeight();
textRect.location[1] = centerRect.location[1] + 20 * pf;
textRect.location[0] =
centerRect.location[0] + SPLASH_WIDTH * 3 / 4 * pf - m_extractButt.m_view->nominalWidth() / 2;
m_extractButt.m_view->resized(root, textRect);
} }
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->resized(root, root);
} }
void SplashScreen::draw(boo::IGraphicsCommandQueue* gfxQ) { void SplashScreen::draw(boo::IGraphicsCommandQueue* gfxQ) {
@ -258,15 +107,9 @@ void SplashScreen::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_title) { if (m_title) {
m_title->draw(gfxQ); m_title->draw(gfxQ);
m_buildInfo->draw(gfxQ); m_buildInfo->draw(gfxQ);
m_badgeIcon->draw(gfxQ);
m_badgeText->draw(gfxQ); m_badgeText->draw(gfxQ);
m_newButt.m_view->draw(gfxQ); m_infoStr->draw(gfxQ);
m_openButt.m_view->draw(gfxQ);
m_extractButt.m_view->draw(gfxQ);
} }
if (m_fileBrowser.m_view)
m_fileBrowser.m_view->draw(gfxQ);
} }
} // namespace metaforce } // namespace metaforce

View File

@ -16,147 +16,19 @@ class SplashScreen : public specter::ModalWindow {
ViewManager& m_vm; ViewManager& m_vm;
zeus::CColor m_textColor; zeus::CColor m_textColor;
zeus::CColor m_textColorClear;
std::unique_ptr<specter::TextView> m_title; std::unique_ptr<specter::TextView> m_title;
std::string m_buildInfoStr; std::string m_buildInfoStr;
std::unique_ptr<specter::MultiLineTextView> m_buildInfo; std::unique_ptr<specter::MultiLineTextView> m_buildInfo;
std::unique_ptr<specter::IconView> m_badgeIcon;
std::unique_ptr<specter::TextView> m_badgeText; std::unique_ptr<specter::TextView> m_badgeText;
std::string m_newString; std::unique_ptr<specter::TextView> m_infoStr;
specter::ViewChild<std::unique_ptr<specter::Button>> m_newButt;
std::string m_openString;
specter::ViewChild<std::unique_ptr<specter::Button>> m_openButt;
std::string m_extractString;
specter::ViewChild<std::unique_ptr<specter::Button>> m_extractButt;
specter::ViewChild<std::unique_ptr<specter::FileBrowser>> m_fileBrowser;
struct NewProjBinding : specter::IButtonBinding {
SplashScreen& m_splash;
hecl::SystemString m_deferPath;
NewProjBinding(SplashScreen& splash) : m_splash(splash) {}
std::string_view name(const specter::Control* control) const override { return m_splash.m_newString.c_str(); }
std::string_view help(const specter::Control* control) const override {
return "Creates an empty project at selected path";
}
void activated(const specter::Button* button, const boo::SWindowCoord& coord) override {
m_splash.m_fileBrowser.m_view.reset(new specter::FileBrowser(
m_splash.rootView().viewRes(), m_splash, m_splash.m_newString, specter::FileBrowser::Type::NewHECLProject,
[&](bool ok, hecl::SystemStringView path) {
if (ok)
m_deferPath = path;
}));
m_splash.updateSize();
m_splash.m_newButt.mouseLeave(coord);
}
} m_newProjBind;
struct OpenProjBinding : specter::IButtonBinding {
SplashScreen& m_splash;
hecl::SystemString m_deferPath;
OpenProjBinding(SplashScreen& splash) : m_splash(splash), m_openRecentMenuRoot(*this) {}
std::string_view name(const specter::Control* control) const override { return m_splash.m_openString.c_str(); }
std::string_view help(const specter::Control* control) const override {
return "Opens an existing project at selected path";
}
void activated(const specter::Button* button, const boo::SWindowCoord& coord) override {
m_splash.m_fileBrowser.m_view.reset(new specter::FileBrowser(
m_splash.rootView().viewRes(), m_splash, m_splash.m_openString, specter::FileBrowser::Type::OpenHECLProject,
[&](bool ok, hecl::SystemStringView path) {
if (ok)
m_deferPath = path;
}));
m_splash.updateSize();
m_splash.m_openButt.mouseLeave(coord);
}
struct OpenRecentMenuRoot : specter::IMenuNode {
OpenProjBinding& m_openProjBind;
OpenRecentMenuRoot(OpenProjBinding& openProjBind) : m_openProjBind(openProjBind) {}
std::string m_text;
const std::string* text() const override { return &m_text; }
struct OpenRecentMenuItem final : specter::IMenuNode {
OpenRecentMenuRoot& m_parent;
hecl::SystemString m_path;
std::string m_text;
const std::string* text() const override { return &m_text; }
void activated(const boo::SWindowCoord& coord) override {
m_parent.m_openProjBind.m_deferPath = m_path;
m_parent.m_openProjBind.m_splash.m_openButt.m_view->closeMenu(coord);
}
OpenRecentMenuItem(OpenRecentMenuRoot& parent, const hecl::SystemString& path)
: m_parent(parent), m_path(path) {
std::vector<hecl::SystemString> pathComps = specter::FileBrowser::PathComponents(path);
if (pathComps.size())
m_text = hecl::SystemUTF8Conv(pathComps.back()).str();
}
};
std::vector<OpenRecentMenuItem> m_items;
size_t subNodeCount() const override { return m_items.size(); }
specter::IMenuNode* subNode(size_t idx) override { return &m_items[idx]; }
void buildNodes(const std::vector<hecl::SystemString>* recentProjects) {
m_items.clear();
if (recentProjects) {
m_items.reserve(recentProjects->size());
for (const hecl::SystemString& path : *recentProjects)
m_items.emplace_back(*this, path);
}
}
} m_openRecentMenuRoot;
MenuStyle menuStyle(const specter::Button* button) const override { return MenuStyle::Auxiliary; }
std::unique_ptr<View> buildMenu(const specter::Button* button) override {
m_openRecentMenuRoot.buildNodes(m_splash.m_vm.recentProjects());
return std::unique_ptr<View>(new specter::Menu(m_splash.rootView().viewRes(), m_splash, &m_openRecentMenuRoot));
}
} m_openProjBind;
struct ExtractProjBinding : specter::IButtonBinding {
SplashScreen& m_splash;
hecl::SystemString m_deferPath;
ExtractProjBinding(SplashScreen& splash) : m_splash(splash) {}
std::string_view name(const specter::Control* control) const override { return m_splash.m_extractString.c_str(); }
std::string_view help(const specter::Control* control) const override {
return "Extracts game image as project at selected path";
}
void activated(const specter::Button* button, const boo::SWindowCoord& coord) override {
m_splash.m_fileBrowser.m_view.reset(
new specter::FileBrowser(m_splash.rootView().viewRes(), m_splash, m_splash.m_extractString,
specter::FileBrowser::Type::OpenFile, [&](bool ok, hecl::SystemStringView path) {
if (ok)
m_deferPath = path;
}));
m_splash.updateSize();
m_splash.m_extractButt.mouseLeave(coord);
}
} m_extractProjBind;
public: public:
SplashScreen(ViewManager& vm, specter::ViewResources& res); SplashScreen(ViewManager& vm, specter::ViewResources& res);
void think() override; void think() override;
void updateContentOpacity(float opacity) override; void updateContentOpacity(float opacity) override;
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) override;
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) override;
void mouseMove(const boo::SWindowCoord&) override;
void mouseEnter(const boo::SWindowCoord&) override;
void mouseLeave(const boo::SWindowCoord&) override;
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&) override;
void touchDown(const boo::STouchCoord&, uintptr_t) override;
void touchUp(const boo::STouchCoord&, uintptr_t) override;
void touchMove(const boo::STouchCoord&, uintptr_t) override;
void charKeyDown(unsigned long, boo::EModifierKey, bool) override;
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool) override;
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) override; void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) override;
void draw(boo::IGraphicsCommandQueue* gfxQ) override; void draw(boo::IGraphicsCommandQueue* gfxQ) override;
}; };

View File

@ -292,7 +292,7 @@ void ViewManager::pushRecentFile(hecl::SystemStringView path) {
} }
void ViewManager::init(boo::IApplication* app) { void ViewManager::init(boo::IApplication* app) {
m_mainWindow = app->newWindow(_SYS_STR("URDE")); m_mainWindow = app->newWindow(_SYS_STR("Metaforce"));
m_mainWindow->showWindow(); m_mainWindow->showWindow();
m_mainWindow->setWaitCursor(true); m_mainWindow->setWaitCursor(true);
if (m_cvarCommons.getFullscreen()) { if (m_cvarCommons.getFullscreen()) {

View File

@ -10,5 +10,5 @@ specter::Icon& GetBadge();
} // namespace metaforce } // namespace metaforce
#ifndef BADGE_PHRASE #ifndef BADGE_PHRASE
#define BADGE_PHRASE "Prototype" #define BADGE_PHRASE "Alpha"
#endif #endif

View File

@ -51,7 +51,7 @@ void ViewResources::prepFontCacheSync() {
m_heading18 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 18.f, dpi); m_heading18 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 18.f, dpi);
if (m_fcacheInterrupt.load()) if (m_fcacheInterrupt.load())
return; return;
m_titleFont = m_fcache->prepMainFont(LatinCharFilter, false, 36.f, dpi); m_titleFont = m_fcache->prepMainFont(LatinCharFilter, false, 24.f, dpi);
if (m_fcacheInterrupt.load()) if (m_fcacheInterrupt.load())
return; return;
m_fcache->closeBuiltinFonts(); m_fcache->closeBuiltinFonts();