summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f3c7a20)
raw | patch | inline | side by side (parent: f3c7a20)
author | Jon A. Cruz <jon@joncruz.org> | |
Tue, 21 Dec 2010 08:13:59 +0000 (00:13 -0800) | ||
committer | Jon A. Cruz <jon@joncruz.org> | |
Tue, 21 Dec 2010 08:13:59 +0000 (00:13 -0800) |
src/widgets/icon.cpp | patch | blob | history |
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index 3b9b47425d3826a40c45fb50f430591a5fe5e829..3e0746edf99f2f3bd73e5724d65a26006e53177b 100644 (file)
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
#include <gtk/gtk.h>
#include <gtkmm.h>
#include <gdkmm/pixbuf.h>
+#include <glibmm/fileutils.h>
#include "path-prefix.h"
#include "preferences.h"
static void imageMapNamedCB(GtkWidget* widget, gpointer user_data);
static bool prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psize);
+
+ static std::list<gchar*> &icons_svg_paths();
+ static guchar *load_svg_pixels(std::list<Glib::ustring> const &names,
+ unsigned lsize, unsigned psize);
+
+ static std::string fileEscape( std::string const & str );
+
+ static void validateCache();
static void setupLegacyNaming();
private:
+ static const std::string magicNumber;
static GtkWidgetClass *parent_class;
static std::map<Glib::ustring, Glib::ustring> legacyNames;
};
+const std::string IconImpl::magicNumber = "1.0";
GtkWidgetClass *IconImpl::parent_class = 0;
std::map<Glib::ustring, Glib::ustring> IconImpl::legacyNames;
gtk_widget_queue_draw( GTK_WIDGET(icon) );
}
+std::string IconImpl::fileEscape( std::string const & str )
+{
+ std::string result;
+ result.reserve(str.size());
+ for ( size_t i = 0; i < str.size(); ++i ) {
+ char ch = str[i];
+ if ( (0x20 <= ch) && !(0x80 & ch) ) {
+ result += ch;
+ } else {
+ result += "\\x";
+ gchar *tmp = g_strdup_printf("%02X", (0x0ff & ch));
+ result += tmp;
+ g_free(tmp);
+ }
+ }
+ return result;
+}
+
+static bool isSizedSubdir( std::string const &name )
+{
+ bool isSized = false;
+ if ( (name.size() > 2) && (name.size() & 1) ) { // needs to be an odd length 3 or more
+ size_t mid = (name.size() - 1) / 2;
+ if ( (name[mid] == 'x') && (name.substr(0, mid) == name.substr(mid + 1)) ) {
+ isSized = true;
+ for ( size_t i = 0; (i < mid) && isSized; ++i ) {
+ isSized &= g_ascii_isdigit(name[i]);
+ }
+ }
+ }
+ return isSized;
+}
+
+void IconImpl::validateCache()
+{
+ std::list<gchar *> &sources = icons_svg_paths();
+ std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons");
+ std::string iconCacheFile = Glib::build_filename( iconCacheDir, "cache.info" );
+
+ std::vector<std::string> filesFound;
+
+ for (std::list<gchar*>::iterator i = sources.begin(); i != sources.end(); ++i) {
+ gchar const* potentialFile = *i;
+ if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) {
+ filesFound.push_back(*i);
+ }
+ }
+
+ unsigned long lastSeen = 0;
+ std::ostringstream out;
+ out << "Inkscape cache v" << std::hex << magicNumber << std::dec << std::endl;
+ out << "Sourcefiles: " << filesFound.size() << std::endl;
+ for ( std::vector<std::string>::iterator it = filesFound.begin(); it != filesFound.end(); ++it ) {
+ GStatBuf st;
+ memset(&st, 0, sizeof(st));
+ if ( !g_stat(it->c_str(), &st) ) {
+ unsigned long when = st.st_mtime;
+ lastSeen = std::max(lastSeen, when);
+ out << std::hex << when << std::dec << " " << fileEscape(*it) << std::endl;
+ } else {
+ out << "0 " << fileEscape(*it) << std::endl;
+ }
+ }
+ std::string wanted = out.str();
+
+ std::string present;
+ {
+ gchar *contents = 0;
+ if ( g_file_get_contents(iconCacheFile.c_str(), &contents, 0, 0) ) {
+ if ( contents ) {
+ present = contents;
+ }
+ g_free(contents);
+ contents = 0;
+ }
+ }
+ bool cacheValid = (present == wanted);
+
+ if ( cacheValid ) {
+ // Check if any cached rasters are out of date
+ Glib::Dir dir(iconCacheDir);
+ for ( Glib::DirIterator it = dir.begin(); cacheValid && (it != dir.end()); ++it ) {
+ if ( isSizedSubdir(*it) ) {
+ std::string subdirName = Glib::build_filename( iconCacheDir, *it );
+ Glib::Dir subdir(subdirName);
+ for ( Glib::DirIterator subit = subdir.begin(); cacheValid && (subit != subdir.end()); ++subit ) {
+ std::string fullpath = Glib::build_filename( subdirName, *subit );
+ if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) {
+ GStatBuf st;
+ memset(&st, 0, sizeof(st));
+ if ( !g_stat(fullpath.c_str(), &st) ) {
+ unsigned long when = st.st_mtime;
+ if ( when < lastSeen ) {
+ cacheValid = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( !cacheValid ) {
+ // Purge existing icons, but not possible future sub-directories.
+ Glib::Dir dir(iconCacheDir);
+ for ( Glib::DirIterator it = dir.begin(); it != dir.end(); ++it ) {
+ if ( isSizedSubdir(*it) ) {
+ std::string subdirName = Glib::build_filename( iconCacheDir, *it );
+ Glib::Dir subdir(subdirName);
+ for ( Glib::DirIterator subit = subdir.begin(); subit != subdir.end(); ++subit ) {
+ std::string fullpath = Glib::build_filename( subdirName, *subit );
+ if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) {
+ g_remove(fullpath.c_str());
+ }
+ }
+ g_rmdir( subdirName.c_str() );
+ }
+ }
+
+ if ( g_file_set_contents(iconCacheFile.c_str(), wanted.c_str(), wanted.size(), 0) ) {
+ // Caching may proceed
+ } else {
+ g_warning("Unable to write cache info file.");
+ }
+ }
+}
static Glib::ustring icon_cache_key(Glib::ustring const &name, unsigned psize);
static GdkPixbuf *get_cached_pixbuf(Glib::ustring const &key);
return pb;
}
-static std::list<gchar*> &icons_svg_paths()
+std::list<gchar*> &IconImpl::icons_svg_paths()
{
static std::list<gchar *> sources;
static bool initialized = false;
}
// this function renders icons from icons.svg and returns the pixels.
-static guchar *load_svg_pixels(std::list<Glib::ustring> const &names,
- unsigned /*lsize*/, unsigned psize)
+guchar *IconImpl::load_svg_pixels(std::list<Glib::ustring> const &names,
+ unsigned /*lsize*/, unsigned psize)
{
bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg");
std::list<gchar *> &sources = icons_svg_paths();
@@ -1194,6 +1331,11 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz
bool loadNeeded = false;
static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk");
static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache");
+ static bool cacheValidated = false;
+ if (!cacheValidated) {
+ cacheValidated = true;
+ validateCache();
+ }
Glib::ustring key = icon_cache_key(name, psize);
if ( !get_cached_pixbuf(key) ) {