Browse Source

Code to load SVG icons into the BitmapCache class.

bubnikv 6 years ago
parent
commit
a36bdefda5

+ 21 - 19
resources/icons/layers.svg

@@ -1,25 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
-<g>
+	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+<g id="layers">
 	<g>
-		<rect x="7.98" y="105" fill="#FFFFFF" width="112.04" height="15"/>
-	</g>
-	<g>
-		<rect x="7.98" y="85.67" fill="#FFFFFF" width="112.04" height="13"/>
-	</g>
-	<g>
-		<rect x="7.98" y="66.33" fill="#FFFFFF" width="112.04" height="11"/>
-	</g>
-	<g>
-		<rect x="7.98" y="47" fill="#ED6B21" width="112.04" height="9"/>
-	</g>
-	<g>
-		<rect x="7.98" y="27.67" fill="#ED6B21" width="112.04" height="7"/>
-	</g>
-	<g>
-		<rect x="7.98" y="8.33" fill="#ED6B21" width="112.04" height="5"/>
+		<g>
+			<rect x="1" y="13" fill="#808080" width="14" height="2"/>
+		</g>
+		<g>
+			<rect x="1" y="10.6" fill="#808080" width="14" height="1.74"/>
+		</g>
+		<g>
+			<rect x="1" y="8.19" fill="#808080" width="14" height="1.47"/>
+		</g>
+		<g>
+			<rect x="1" y="5.79" fill="#ED6B21" width="14" height="1.2"/>
+		</g>
+		<g>
+			<rect x="1" y="3.39" fill="#ED6B21" width="14" height="0.93"/>
+		</g>
+		<g>
+			<rect x="1" y="0.99" fill="#808080" width="14" height="0.67"/>
+		</g>
 	</g>
 </g>
 </svg>

+ 73 - 0
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 <wx/rawbmp.h>
 #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<unsigned char> 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);

+ 6 - 0
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<wxBitmap> &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); }

+ 1 - 4
src/slic3r/GUI/GLTexture.cpp

@@ -11,15 +11,11 @@
 #include <vector>
 #include <algorithm>
 
-#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;
     }
 

+ 1 - 1
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");

+ 11 - 12
src/slic3r/GUI/wxExtensions.cpp

@@ -8,6 +8,8 @@
 #include <wx/dcclient.h>
 #include <wx/numformatter.h>
 
+#include <boost/algorithm/string/replace.hpp>
+
 #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() {