Creates an RTImage cache

Fixes:
- Fixes GUI issue on Windows (GDI handles limit reached)
- Fixes an incorrect icon name in Perspective tool
- Adds robustness RTScalable::loadSurfaceFromIcon function
This commit is contained in:
Pandagrapher
2022-09-02 19:15:42 +02:00
parent 35ce0d1227
commit 1c85926200
6 changed files with 130 additions and 21 deletions

View File

@@ -120,7 +120,7 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M("
RTImage* const ipersVL = Gtk::manage (new RTImage ("perspective-vertical-bottom-small")); RTImage* const ipersVL = Gtk::manage (new RTImage ("perspective-vertical-bottom-small"));
RTImage* const ipersVR = Gtk::manage (new RTImage ("perspective-vertical-top-small")); RTImage* const ipersVR = Gtk::manage (new RTImage ("perspective-vertical-top-small"));
RTImage* const ipers_auto_pitch = Gtk::manage (new RTImage ("perspective-vertical-botton", Gtk::ICON_SIZE_BUTTON)); RTImage* const ipers_auto_pitch = Gtk::manage (new RTImage ("perspective-vertical-bottom", Gtk::ICON_SIZE_BUTTON));
RTImage* const ipers_auto_yaw = Gtk::manage (new RTImage ("perspective-horizontal-left", Gtk::ICON_SIZE_BUTTON)); RTImage* const ipers_auto_yaw = Gtk::manage (new RTImage ("perspective-horizontal-left", Gtk::ICON_SIZE_BUTTON));
RTImage* const ipers_auto_pitch_yaw = Gtk::manage (new RTImage ("perspective-horizontal-vertical", Gtk::ICON_SIZE_BUTTON)); RTImage* const ipers_auto_pitch_yaw = Gtk::manage (new RTImage ("perspective-horizontal-vertical", Gtk::ICON_SIZE_BUTTON));

View File

@@ -21,21 +21,95 @@
#include "rtimage.h" #include "rtimage.h"
#include "rtsurface.h"
std::map<std::pair<Glib::ustring, Gtk::IconSize>, std::shared_ptr<RTSurface>> RTImageCache::cache;
std::shared_ptr<RTSurface> RTImageCache::getCachedSurface(const Glib::ustring &icon_name, const Gtk::IconSize icon_size)
{
// Look for an existing cached icon
const auto key = std::pair<Glib::ustring, Gtk::IconSize>(icon_name, icon_size);
const auto item = cache.find(key);
if (item != cache.end()) { // A cached icon exists
return item->second;
} else { // Create the icon
auto surface = std::shared_ptr<RTSurface>(new RTSurface(icon_name, icon_size));
// Add the surface to the cache if the icon exist
if (surface) {
cache.insert({key, surface});
}
return surface;
}
}
void RTImageCache::updateCache()
{
// Iterate over cache to updated RTSurface
for (auto const& item : cache) {
item.second->updateSurface();
}
}
RTImage::RTImage () {} RTImage::RTImage () {}
RTImage::RTImage (const Glib::ustring& iconName, const Gtk::IconSize iconSize) : RTImage::RTImage (const Glib::ustring& iconName, const Gtk::IconSize iconSize) :
Gtk::Image(iconName, iconSize), Gtk::Image(),
size(iconSize) size(iconSize),
icon_name(iconName)
{ {
// Set surface from icon cache
surface = RTImageCache::getCachedSurface(this->icon_name, this->size);
// Add it to the RTImage if surface exists
if (surface) {
set(surface->get());
}
} }
void RTImage::set_from_icon_name(const Glib::ustring& iconName) void RTImage::set_from_icon_name(const Glib::ustring& iconName)
{ {
Gtk::Image::set_from_icon_name(iconName, this->size); this->icon_name = iconName;
// Set surface from icon cache
surface = RTImageCache::getCachedSurface(this->icon_name, this->size);
// Add it to the RTImage if surface exists
if (surface) {
set(surface->get());
}
} }
void RTImage::set_from_icon_name(const Glib::ustring& iconName, const Gtk::IconSize iconSize) void RTImage::set_from_icon_name(const Glib::ustring& iconName, const Gtk::IconSize iconSize)
{ {
this->icon_name = iconName;
this->size = iconSize; this->size = iconSize;
Gtk::Image::set_from_icon_name(iconName, this->size);
// Set surface from icon cache
surface = RTImageCache::getCachedSurface(this->icon_name, this->size);
// Add it to the RTImage if surface exists
if (surface) {
set(surface->get());
}
}
int RTImage::get_width()
{
if (surface) {
return surface->getWidth();
}
return -1;
}
int RTImage::get_height()
{
if (surface) {
return surface->getHeight();
}
return -1;
} }

View File

@@ -20,7 +20,18 @@
*/ */
#pragma once #pragma once
#include <gtkmm/image.h> #include <gtkmm.h>
class RTSurface;
class RTImageCache final
{
private:
static std::map<std::pair<Glib::ustring, Gtk::IconSize>, std::shared_ptr<RTSurface>> cache;
public:
static std::shared_ptr<RTSurface> getCachedSurface(const Glib::ustring &icon_name, const Gtk::IconSize icon_size);
static void updateCache();
};
/** /**
* @brief A derived class of Gtk::Image in order to handle theme-related icon sets. * @brief A derived class of Gtk::Image in order to handle theme-related icon sets.
@@ -29,6 +40,8 @@ class RTImage final : public Gtk::Image
{ {
private: private:
Gtk::IconSize size; Gtk::IconSize size;
Glib::ustring icon_name;
std::shared_ptr<RTSurface> surface;
public: public:
RTImage (); RTImage ();
@@ -36,4 +49,7 @@ public:
void set_from_icon_name(const Glib::ustring& iconName); void set_from_icon_name(const Glib::ustring& iconName);
void set_from_icon_name(const Glib::ustring& iconName, const Gtk::IconSize iconSize); void set_from_icon_name(const Glib::ustring& iconName, const Gtk::IconSize iconSize);
int get_width();
int get_height();
}; };

View File

@@ -68,10 +68,22 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromIcon(const Glib::u
// Looking for corresponding icon (if existing) // Looking for corresponding icon (if existing)
const auto iconInfo = theme->lookup_icon(iconName, size); const auto iconInfo = theme->lookup_icon(iconName, size);
if (!iconInfo) {
if (rtengine::settings->verbose) {
std::cerr << "Failed to load icon \"" << iconName << "\" for size " << size << "px" << std::endl;
}
return surf;
}
const auto iconPath = iconInfo.get_filename(); const auto iconPath = iconInfo.get_filename();
if ((iconPath.empty() || !iconInfo) && rtengine::settings->verbose) { if (iconPath.empty()) {
std::cerr << "Failed to load icon \"" << iconName << "\" for size " << size << "px" << std::endl; if (rtengine::settings->verbose) {
std::cerr << "Failed to load icon \"" << iconName << "\" for size " << size << "px" << std::endl;
}
return surf; return surf;
} }

View File

@@ -161,19 +161,7 @@ Cairo::RefPtr<Cairo::ImageSurface> RTSurface::get()
{ {
if (dpiBack != RTScalable::getDPI() || if (dpiBack != RTScalable::getDPI() ||
scaleBack != RTScalable::getScale()) { scaleBack != RTScalable::getScale()) {
switch (type) { updateSurface();
case RTSurface::IconType :
surface = RTScalable::loadSurfaceFromIcon(name, icon_size);
break;
case RTSurface::PNGType :
surface = RTScalable::loadSurfaceFromPNG(name);
break;
case RTSurface::SVGType :
surface = RTScalable::loadSurfaceFromSVG(name);
break;
default :
break;
}
// Save new DPI and scale // Save new DPI and scale
dpiBack = RTScalable::getDPI(); dpiBack = RTScalable::getDPI();
@@ -182,3 +170,21 @@ Cairo::RefPtr<Cairo::ImageSurface> RTSurface::get()
return surface; return surface;
} }
void RTSurface::updateSurface()
{
// Update surface based on the scale
switch (type) {
case RTSurface::IconType :
surface = RTScalable::loadSurfaceFromIcon(name, icon_size);
break;
case RTSurface::PNGType :
surface = RTScalable::loadSurfaceFromPNG(name);
break;
case RTSurface::SVGType :
surface = RTScalable::loadSurfaceFromSVG(name);
break;
default :
break;
}
}

View File

@@ -52,4 +52,5 @@ public:
bool hasSurface(); bool hasSurface();
Cairo::RefPtr<Cairo::ImageSurface> get(); Cairo::RefPtr<Cairo::ImageSurface> get();
void updateSurface();
}; };