mirror of https://github.com/KLayout/klayout.git
WIP: Added font controller
This enables font packages: packages can now provide fonts by featuring a "fonts" directory with the font layouts. This commit also adds the capability to dynamically add fonts. The Glyphs system is decoupled from the application's system path and the BASIC.TEXT PCell parameters are non-cached to enable dynamic updates.
This commit is contained in:
parent
a7038282ce
commit
6ba251cf2a
|
|
@ -230,6 +230,9 @@ HEADERS = \
|
|||
dbGlyphs.h \
|
||||
dbCommon.h
|
||||
|
||||
RESOURCES = \
|
||||
dbResources.qrc
|
||||
|
||||
INCLUDEPATH += ../tl ../gsi
|
||||
DEPENDPATH += ../tl ../gsi
|
||||
LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi
|
||||
|
|
|
|||
|
|
@ -299,12 +299,25 @@ TextGenerator::default_generator ()
|
|||
return fonts.empty () ? 0 : &fonts [0];
|
||||
}
|
||||
|
||||
|
||||
static std::vector<std::string> s_font_paths;
|
||||
static std::vector<TextGenerator> s_fonts;
|
||||
static bool s_fonts_loaded = false;
|
||||
|
||||
void
|
||||
TextGenerator::set_font_paths (const std::vector<std::string> &paths)
|
||||
{
|
||||
s_font_paths = paths;
|
||||
s_fonts.clear ();
|
||||
s_fonts_loaded = false;
|
||||
}
|
||||
|
||||
const std::vector<TextGenerator> &
|
||||
TextGenerator::generators ()
|
||||
{
|
||||
static std::vector<TextGenerator> m_fonts;
|
||||
if (! s_fonts_loaded) {
|
||||
|
||||
if (m_fonts.empty ()) {
|
||||
s_fonts.clear ();
|
||||
|
||||
const char *resources[] = {
|
||||
":/fonts/std_font.gds"
|
||||
|
|
@ -312,42 +325,47 @@ TextGenerator::generators ()
|
|||
|
||||
for (size_t i = 0 ; i < sizeof (resources) / sizeof (resources [0]); ++i) {
|
||||
try {
|
||||
m_fonts.push_back (TextGenerator ());
|
||||
m_fonts.back ().load_from_resource (resources [i]);
|
||||
tl::log << "Loading font from resource " << resources [i] << " ..";
|
||||
s_fonts.push_back (TextGenerator ());
|
||||
s_fonts.back ().load_from_resource (resources [i]);
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
m_fonts.pop_back ();
|
||||
s_fonts.pop_back ();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> system_path = tl::get_klayout_path ();
|
||||
|
||||
// scan for font files
|
||||
for (std::vector<std::string>::const_iterator p = system_path.begin (); p != system_path.end (); ++p) {
|
||||
for (std::vector<std::string>::const_iterator p = s_font_paths.begin (); p != s_font_paths.end (); ++p) {
|
||||
|
||||
QDir fp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("fonts"));
|
||||
QDir fp = QDir (tl::to_qstring (*p));
|
||||
if (fp.exists ()) {
|
||||
|
||||
QStringList name_filters;
|
||||
name_filters << QString::fromUtf8 ("*");
|
||||
QStringList name_filters;
|
||||
name_filters << QString::fromUtf8 ("*");
|
||||
|
||||
QStringList font_files = fp.entryList (name_filters, QDir::Files);
|
||||
for (QStringList::const_iterator ff = font_files.begin (); ff != font_files.end (); ++ff) {
|
||||
QStringList font_files = fp.entryList (name_filters, QDir::Files);
|
||||
for (QStringList::const_iterator ff = font_files.begin (); ff != font_files.end (); ++ff) {
|
||||
|
||||
try {
|
||||
tl::log << "Loading font from " << tl::to_string (fp.filePath (*ff)) << " ..";
|
||||
s_fonts.push_back (TextGenerator ());
|
||||
s_fonts.back ().load_from_file (tl::to_string (fp.filePath (*ff)));
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
s_fonts.pop_back ();
|
||||
}
|
||||
|
||||
try {
|
||||
m_fonts.push_back (TextGenerator ());
|
||||
m_fonts.back ().load_from_file (tl::to_string (fp.filePath (*ff)));
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
m_fonts.pop_back ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s_fonts_loaded = true;
|
||||
|
||||
}
|
||||
|
||||
return m_fonts;
|
||||
return s_fonts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,12 @@ public:
|
|||
*/
|
||||
static const std::vector<TextGenerator> &generators ();
|
||||
|
||||
/**
|
||||
* @brief Sets the search path for font files
|
||||
* The given folders are scanned for font files.
|
||||
*/
|
||||
static void set_font_paths (const std::vector<std::string> &paths);
|
||||
|
||||
/**
|
||||
* @brief Returns the font with the given name
|
||||
* If no font with that name exsist, 0 is returned.
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ public:
|
|||
*/
|
||||
const std::vector<PCellParameterDeclaration> ¶meter_declarations () const
|
||||
{
|
||||
if (! m_has_parameter_declarations) {
|
||||
if (! m_has_parameter_declarations || ! wants_parameter_declaration_caching ()) {
|
||||
m_parameter_declarations = get_parameter_declarations ();
|
||||
m_has_parameter_declarations = true;
|
||||
}
|
||||
|
|
@ -495,6 +495,18 @@ public:
|
|||
*/
|
||||
pcell_parameters_type map_parameters (const std::map<std::string, tl::Variant> &named_parameters) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Gets a value indicating whether the PCell wants caching of the parameter declarations
|
||||
*
|
||||
* Some PCells with a dynamic parameter definition may not want paramater declaration caching. These
|
||||
* PCells can override this method and return false.
|
||||
*/
|
||||
virtual bool wants_parameter_declaration_caching () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_ref_count;
|
||||
pcell_id_type m_id;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/fonts">
|
||||
<file>std_font.gds</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -58,7 +58,8 @@ HEADERS = \
|
|||
laySaltModel.h \
|
||||
laySaltController.h \
|
||||
laySignalHandler.h \
|
||||
layLibraryController.h
|
||||
layLibraryController.h \
|
||||
layFontController.h
|
||||
|
||||
FORMS = \
|
||||
ClipDialog.ui \
|
||||
|
|
@ -162,7 +163,8 @@ SOURCES = \
|
|||
laySaltModel.cc \
|
||||
laySaltController.cc \
|
||||
laySignalHandler.cc \
|
||||
layLibraryController.cc
|
||||
layLibraryController.cc \
|
||||
layFontController.cc
|
||||
|
||||
RESOURCES = layBuildInMacros.qrc \
|
||||
layHelpResources.qrc \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "layFontController.h"
|
||||
#include "layApplication.h"
|
||||
#include "laySaltController.h"
|
||||
#include "layConfig.h"
|
||||
#include "layMainWindow.h"
|
||||
#include "dbGlyphs.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
FontController::FontController ()
|
||||
: m_file_watcher (0),
|
||||
dm_sync_dirs (this, &FontController::sync_dirs)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FontController::initialize (lay::PluginRoot * /*root*/)
|
||||
{
|
||||
// NOTE: we initialize the dirs in the stage once to have them available for the autorun
|
||||
// macros. We'll do that later again in order to pull in the dirs from the packages.
|
||||
sync_dirs ();
|
||||
}
|
||||
|
||||
void
|
||||
FontController::initialized (lay::PluginRoot * /*root*/)
|
||||
{
|
||||
if (lay::SaltController::instance ()) {
|
||||
connect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
|
||||
}
|
||||
|
||||
if (! m_file_watcher) {
|
||||
m_file_watcher = new tl::FileSystemWatcher (this);
|
||||
connect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
}
|
||||
|
||||
sync_dirs ();
|
||||
}
|
||||
|
||||
void
|
||||
FontController::uninitialize (lay::PluginRoot * /*root*/)
|
||||
{
|
||||
if (m_file_watcher) {
|
||||
disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
disconnect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
delete m_file_watcher;
|
||||
m_file_watcher = 0;
|
||||
}
|
||||
|
||||
if (lay::SaltController::instance ()) {
|
||||
disconnect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FontController::get_options (std::vector < std::pair<std::string, std::string> > & /*options*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
FontController::get_menu_entries (std::vector<lay::MenuEntry> & /*menu_entries*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool
|
||||
FontController::configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FontController::config_finalize()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool
|
||||
FontController::can_exit (lay::PluginRoot * /*root*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FontController::sync_dirs ()
|
||||
{
|
||||
if (! m_file_watcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_file_watcher->clear ();
|
||||
m_file_watcher->enable (false);
|
||||
|
||||
std::vector<std::string> paths = lay::Application::instance ()->klayout_path ();
|
||||
|
||||
// add the salt grains as potential sources for library definitions
|
||||
|
||||
lay::SaltController *sc = lay::SaltController::instance ();
|
||||
if (sc) {
|
||||
for (lay::Salt::flat_iterator g = sc->salt ().begin_flat (); g != sc->salt ().end_flat (); ++g) {
|
||||
paths.push_back ((*g)->path ());
|
||||
}
|
||||
}
|
||||
|
||||
// scan for font directories
|
||||
|
||||
std::vector<std::string> font_paths;
|
||||
|
||||
for (std::vector <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
|
||||
QDir fp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("fonts"));
|
||||
if (fp.exists ()) {
|
||||
m_file_watcher->add_file (tl::to_string (fp.absolutePath ()));
|
||||
font_paths.push_back (tl::to_string (fp.absolutePath ()));
|
||||
}
|
||||
}
|
||||
|
||||
db::TextGenerator::set_font_paths (font_paths);
|
||||
|
||||
m_file_watcher->enable (true);
|
||||
}
|
||||
|
||||
void
|
||||
FontController::sync_with_external_sources ()
|
||||
{
|
||||
tl::log << tl::to_string (tr ("Package updates - updating fonts"));
|
||||
dm_sync_dirs ();
|
||||
}
|
||||
|
||||
void
|
||||
FontController::file_watcher_triggered ()
|
||||
{
|
||||
tl::log << tl::to_string (tr ("Detected file system change in fonts - updating"));
|
||||
dm_sync_dirs ();
|
||||
}
|
||||
|
||||
FontController *
|
||||
FontController::instance ()
|
||||
{
|
||||
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
|
||||
FontController *sc = dynamic_cast <FontController *> (cls.operator-> ());
|
||||
if (sc) {
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The singleton instance of the library controller
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> font_controller_decl (new lay::FontController (), 160, "FontController");
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_layFontController
|
||||
#define HDR_layFontController
|
||||
|
||||
#include "layCommon.h"
|
||||
#include "layPlugin.h"
|
||||
#include "tlFileSystemWatcher.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class FontManagerDialog;
|
||||
class MainWindow;
|
||||
|
||||
/**
|
||||
* @brief A controller for the fonts
|
||||
*
|
||||
* This object is a singleton that acts as a controller
|
||||
* for the font management for the Glyphs. The controller is responsible
|
||||
* to managing the fonts and notifying library consumers
|
||||
* of changes.
|
||||
*
|
||||
* By making the controller a PluginDeclaration it will receive
|
||||
* initialization and configuration calls.
|
||||
*/
|
||||
class FontController
|
||||
: public lay::PluginDeclaration, public tl::Object
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
FontController ();
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
virtual void initialize (lay::PluginRoot *root);
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
virtual void initialized (lay::PluginRoot *root);
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
virtual void uninitialize (lay::PluginRoot *root);
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
void get_options (std::vector < std::pair<std::string, std::string> > &options) const;
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const;
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
bool configure (const std::string &key, const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
void config_finalize();
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of the PluginDeclaration interface
|
||||
*/
|
||||
bool can_exit (lay::PluginRoot *root) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the singleton instance for this object
|
||||
*/
|
||||
static FontController *instance ();
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Called when the file watcher detects a change in the file system
|
||||
*/
|
||||
void file_watcher_triggered ();
|
||||
|
||||
/**
|
||||
* @brief Called when the salt (packages) has changed
|
||||
*/
|
||||
void sync_with_external_sources ();
|
||||
|
||||
private:
|
||||
tl::FileSystemWatcher *m_file_watcher;
|
||||
tl::DeferredMethod<FontController> dm_sync_dirs;
|
||||
|
||||
void sync_dirs ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ LibraryController::instance ()
|
|||
}
|
||||
|
||||
// The singleton instance of the library controller
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> salt_controller_decl (new lay::LibraryController (), 150, "LibraryController");
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> library_controller_decl (new lay::LibraryController (), 150, "LibraryController");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,17 @@ public:
|
|||
*/
|
||||
virtual std::vector<db::PCellParameterDeclaration> get_parameter_declarations () const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Returns a value indicating that this PCell wants to update it's parameter declarations dynamically
|
||||
*
|
||||
* This is be required because the fonts can be updated dynamically when new packages are installed.
|
||||
*/
|
||||
virtual bool wants_parameter_declaration_caching () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
int get_font_index (const db::pcell_parameters_type ¶meters) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,2 @@
|
|||
<RCC>
|
||||
<qresource prefix="/fonts" >
|
||||
<file>std_font.gds</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
Loading…
Reference in New Issue