diff --git a/src/db/db.pro b/src/db/db.pro index 18190dbba..b43b57f12 100644 --- a/src/db/db.pro +++ b/src/db/db.pro @@ -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 diff --git a/src/db/dbGlyphs.cc b/src/db/dbGlyphs.cc index 4954e2bea..112caaa28 100644 --- a/src/db/dbGlyphs.cc +++ b/src/db/dbGlyphs.cc @@ -299,12 +299,25 @@ TextGenerator::default_generator () return fonts.empty () ? 0 : &fonts [0]; } + +static std::vector s_font_paths; +static std::vector s_fonts; +static bool s_fonts_loaded = false; + +void +TextGenerator::set_font_paths (const std::vector &paths) +{ + s_font_paths = paths; + s_fonts.clear (); + s_fonts_loaded = false; +} + const std::vector & TextGenerator::generators () { - static std::vector 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 system_path = tl::get_klayout_path (); - // scan for font files - for (std::vector::const_iterator p = system_path.begin (); p != system_path.end (); ++p) { + for (std::vector::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; } } diff --git a/src/db/dbGlyphs.h b/src/db/dbGlyphs.h index 18d9be721..73a6d3864 100644 --- a/src/db/dbGlyphs.h +++ b/src/db/dbGlyphs.h @@ -188,6 +188,12 @@ public: */ static const std::vector &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 &paths); + /** * @brief Returns the font with the given name * If no font with that name exsist, 0 is returned. diff --git a/src/db/dbPCellDeclaration.h b/src/db/dbPCellDeclaration.h index ea669a50a..f957e1868 100644 --- a/src/db/dbPCellDeclaration.h +++ b/src/db/dbPCellDeclaration.h @@ -453,7 +453,7 @@ public: */ const std::vector ¶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 &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; diff --git a/src/db/dbResources.qrc b/src/db/dbResources.qrc new file mode 100644 index 000000000..92058dab4 --- /dev/null +++ b/src/db/dbResources.qrc @@ -0,0 +1,5 @@ + + + std_font.gds + + diff --git a/src/lib/std_font.gds b/src/db/std_font.gds similarity index 100% rename from src/lib/std_font.gds rename to src/db/std_font.gds diff --git a/src/lay/lay.pro b/src/lay/lay.pro index ff6ebd3d3..079155bfd 100644 --- a/src/lay/lay.pro +++ b/src/lay/lay.pro @@ -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 \ diff --git a/src/lay/layFontController.cc b/src/lay/layFontController.cc new file mode 100644 index 000000000..de36f4bca --- /dev/null +++ b/src/lay/layFontController.cc @@ -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 + +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 > & /*options*/) const +{ + // .. nothing yet .. +} + +void +FontController::get_menu_entries (std::vector & /*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 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 font_paths; + + for (std::vector ::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::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { + FontController *sc = dynamic_cast (cls.operator-> ()); + if (sc) { + return sc; + } + } + return 0; +} + +// The singleton instance of the library controller +static tl::RegisteredClass font_controller_decl (new lay::FontController (), 160, "FontController"); + +} + diff --git a/src/lay/layFontController.h b/src/lay/layFontController.h new file mode 100644 index 000000000..5c1e48e28 --- /dev/null +++ b/src/lay/layFontController.h @@ -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 +#include + +#include + +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 > &options) const; + + /** + * @brief Reimplementation of the PluginDeclaration interface + */ + void get_menu_entries (std::vector &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 dm_sync_dirs; + + void sync_dirs (); +}; + +} + +#endif + diff --git a/src/lay/layLibraryController.cc b/src/lay/layLibraryController.cc index 0548c2c49..88334f7be 100644 --- a/src/lay/layLibraryController.cc +++ b/src/lay/layLibraryController.cc @@ -255,7 +255,7 @@ LibraryController::instance () } // The singleton instance of the library controller -static tl::RegisteredClass salt_controller_decl (new lay::LibraryController (), 150, "LibraryController"); +static tl::RegisteredClass library_controller_decl (new lay::LibraryController (), 150, "LibraryController"); } diff --git a/src/lib/libBasicText.h b/src/lib/libBasicText.h index b0ef3dfa0..8f36f4662 100644 --- a/src/lib/libBasicText.h +++ b/src/lib/libBasicText.h @@ -83,6 +83,17 @@ public: */ virtual std::vector 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; }; diff --git a/src/lib/libResources.qrc b/src/lib/libResources.qrc index d98df72d0..03585ec03 100644 --- a/src/lib/libResources.qrc +++ b/src/lib/libResources.qrc @@ -1,5 +1,2 @@ - - std_font.gds -