diff --git a/resources/icons/layers.svg b/resources/icons/layers.svg
index 7718a8cbd..da5dec21d 100644
--- a/resources/icons/layers.svg
+++ b/resources/icons/layers.svg
@@ -1,25 +1,27 @@
-
+
diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp
index 16baa1629..4c7f999ff 100644
--- a/src/slic3r/GUI/BitmapCache.cpp
+++ b/src/slic3r/GUI/BitmapCache.cpp
@@ -1,5 +1,7 @@
#include "BitmapCache.hpp"
+#include "libslic3r/Utils.hpp"
+
#if ! defined(WIN32) && ! defined(__APPLE__)
#define BROKEN_ALPHA
#endif
@@ -9,6 +11,11 @@
#include
#endif /* BROKEN_ALPHA */
+#define NANOSVG_IMPLEMENTATION
+#include "nanosvg/nanosvg.h"
+#define NANOSVGRAST_IMPLEMENTATION
+#include "nanosvg/nanosvgrast.h"
+
namespace Slic3r { namespace GUI {
void BitmapCache::clear()
@@ -155,6 +162,72 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
#endif
}
+wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data)
+{
+ wxImage image(width, height);
+ image.InitAlpha();
+ unsigned char *rgb = image.GetData();
+ unsigned char *alpha = image.GetAlpha();
+ unsigned int pixels = width * height;
+ for (unsigned int i = 0; i < pixels; ++ i) {
+ *rgb ++ = *raw_data ++;
+ *rgb ++ = *raw_data ++;
+ *rgb ++ = *raw_data ++;
+ *alpha ++ = *raw_data ++;
+ }
+ return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
+}
+
+wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int height)
+{
+ std::string bitmap_key = bitmap_name + "-h" + std::to_string(height);
+ auto it = m_map.find(bitmap_key);
+ if (it != m_map.end())
+ return it->second;
+
+ wxImage image;
+ if (! image.LoadFile(Slic3r::GUI::from_u8(Slic3r::var(bitmap_name + ".png")), wxBITMAP_TYPE_PNG) ||
+ image.GetWidth() == 0 || image.GetHeight() == 0)
+ return nullptr;
+ if (image.GetHeight() != height)
+ image.Rescale(int(0.5f + float(image.GetWidth()) * height / image.GetHeight()), height, wxIMAGE_QUALITY_BILINEAR);
+ return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
+}
+
+wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int target_height)
+{
+ std::string bitmap_key = bitmap_name + "-h" + std::to_string(target_height);
+ auto it = m_map.find(bitmap_key);
+ if (it != m_map.end())
+ return it->second;
+
+ NSVGimage *image = ::nsvgParseFromFile(Slic3r::var(bitmap_name + ".svg").c_str(), "px", 96.0f);
+ if (image == nullptr)
+ return nullptr;
+
+ float scale = (float)target_height / image->height;
+ int width = (int)(scale * image->width + 0.5f);
+ int height = (int)(scale * image->height + 0.5f);
+ int n_pixels = width * height;
+ if (n_pixels <= 0) {
+ ::nsvgDelete(image);
+ return nullptr;
+ }
+
+ NSVGrasterizer *rast = ::nsvgCreateRasterizer();
+ if (rast == nullptr) {
+ ::nsvgDelete(image);
+ return nullptr;
+ }
+
+ std::vector data(n_pixels * 4, 0);
+ ::nsvgRasterize(rast, image, 0, 0, scale, data.data(), width, height, width * 4);
+ ::nsvgDeleteRasterizer(rast);
+ ::nsvgDelete(image);
+
+ return this->insert_raw_rgba(bitmap_key, width, height, data.data());
+}
+
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency)
{
wxImage image(width, height);
diff --git a/src/slic3r/GUI/BitmapCache.hpp b/src/slic3r/GUI/BitmapCache.hpp
index 0cb70d28b..ce5eb3c77 100644
--- a/src/slic3r/GUI/BitmapCache.hpp
+++ b/src/slic3r/GUI/BitmapCache.hpp
@@ -29,6 +29,12 @@ public:
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3);
wxBitmap* insert(const std::string &name, const std::vector &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); }
wxBitmap* insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end);
+ wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data);
+
+ // Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height if nonzero.
+ wxBitmap* load_png(const std::string &bitmap_key, unsigned int height = 0);
+ // Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height.
+ wxBitmap* load_svg(const std::string &bitmap_key, unsigned int height);
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index b48ca2044..68369d9d0 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -11,15 +11,11 @@
#include
#include
-#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
-#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include "libslic3r/Utils.hpp"
-#include "libslic3r/Utils.hpp"
-
namespace Slic3r {
namespace GUI {
@@ -378,6 +374,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
if (n_pixels <= 0)
{
reset();
+ nsvgDelete(image);
return false;
}
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 631050f29..a91dae026 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1446,7 +1446,7 @@ void TabFilament::build()
line.append_option(optgroup->get_option("bed_temperature"));
optgroup->append_line(line);
- page = add_options_page(_(L("Cooling")), "hourglass.png");
+ page = add_options_page(_(L("Cooling")), "cooling");
optgroup = page->new_optgroup(_(L("Enable")));
optgroup->append_single_option_line("fan_always_on");
optgroup->append_single_option_line("cooling");
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 55544f28e..09096cb05 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -8,6 +8,8 @@
#include
#include
+#include
+
#include "BitmapCache.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
@@ -421,19 +423,16 @@ void PrusaCollapsiblePaneMSW::Collapse(bool collapse)
// PrusaObjectDataViewModelNode
// ----------------------------------------------------------------------------
-wxBitmap create_scaled_bitmap(const std::string& bmp_name)
+wxBitmap create_scaled_bitmap(const std::string& bmp_name_in)
{
- const double scale_f = Slic3r::GUI::wxGetApp().em_unit()* 0.1;//GetContentScaleFactor();
- if (scale_f == 1.0)
- return wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(bmp_name)), wxBITMAP_TYPE_PNG);
-// else if (scale_f == 2.0) // use biger icon
-// return wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(bmp_name_X2)), wxBITMAP_TYPE_PNG);
-
- wxImage img = wxImage(Slic3r::GUI::from_u8(Slic3r::var(bmp_name)), wxBITMAP_TYPE_PNG);
- const int sz_w = int(img.GetWidth()*scale_f);
- const int sz_h = int(img.GetHeight()*scale_f);
- img.Rescale(sz_w, sz_h, wxIMAGE_QUALITY_BILINEAR);
- return wxBitmap(img);
+ static Slic3r::GUI::BitmapCache cache;
+ const auto height = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * 1.6f + 0.5f);
+ std::string bmp_name = bmp_name_in;
+ boost::replace_last(bmp_name, ".png", "");
+ wxBitmap *bmp = cache.load_svg(bmp_name, height);
+ if (bmp == nullptr)
+ bmp = cache.load_png(bmp_name, height);
+ return *bmp;
}
void PrusaObjectDataViewModelNode::set_object_action_icon() {