mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "BitmapCache.hpp"
 | |
| 
 | |
| #if ! defined(WIN32) && ! defined(__APPLE__)
 | |
| #define BROKEN_ALPHA
 | |
| #endif
 | |
| 
 | |
| #ifdef BROKEN_ALPHA
 | |
|     #include <wx/mstream.h>
 | |
|     #include <wx/rawbmp.h>
 | |
| #endif /* BROKEN_ALPHA */
 | |
| 
 | |
| namespace Slic3r { namespace GUI {
 | |
| 
 | |
| void BitmapCache::clear()
 | |
| {
 | |
|     for (std::pair<const std::string, wxBitmap*> &bitmap : m_map)
 | |
|         delete bitmap.second;
 | |
| }
 | |
| 
 | |
| static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image)
 | |
| {
 | |
| #ifdef BROKEN_ALPHA
 | |
|     wxMemoryOutputStream stream;
 | |
|     image.SaveFile(stream, wxBITMAP_TYPE_PNG);
 | |
|     wxStreamBuffer *buf = stream.GetOutputStreamBuffer();
 | |
|     return wxBitmap::NewFromPNGData(buf->GetBufferStart(), buf->GetBufferSize());
 | |
| #else
 | |
|     return wxBitmap(std::move(image));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height)
 | |
| {
 | |
|     wxBitmap *bitmap = nullptr;
 | |
|     auto      it     = m_map.find(bitmap_key);
 | |
|     if (it == m_map.end()) {
 | |
|         bitmap = new wxBitmap(width, height);
 | |
|         m_map[bitmap_key] = bitmap;
 | |
|     } else {
 | |
|         bitmap = it->second;
 | |
|         if (bitmap->GetWidth() != width || bitmap->GetHeight() != height)
 | |
|             bitmap->Create(width, height);
 | |
|     }
 | |
| #ifndef BROKEN_ALPHA
 | |
|     bitmap->UseAlpha();
 | |
| #endif
 | |
|     return bitmap;
 | |
| }
 | |
| 
 | |
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp)
 | |
| {
 | |
|     wxBitmap *bitmap = nullptr;
 | |
|     auto      it     = m_map.find(bitmap_key);
 | |
|     if (it == m_map.end()) {
 | |
|         bitmap = new wxBitmap(bmp);
 | |
|         m_map[bitmap_key] = bitmap;
 | |
|     } else {
 | |
|         bitmap = it->second;
 | |
|         *bitmap = bmp;
 | |
|     }
 | |
|     return bitmap;
 | |
| }
 | |
| 
 | |
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2)
 | |
| {
 | |
|     // Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
 | |
|     const wxBitmap bmps[2] = { bmp, bmp2 };
 | |
|     return this->insert(bitmap_key, bmps, bmps + 2);
 | |
| }
 | |
| 
 | |
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3)
 | |
| {
 | |
|     // Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
 | |
|     const wxBitmap bmps[3] = { bmp, bmp2, bmp3 };
 | |
|     return this->insert(bitmap_key, bmps, bmps + 3);
 | |
| }
 | |
| 
 | |
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *begin, const wxBitmap *end)
 | |
| {
 | |
|     size_t width  = 0;
 | |
|     size_t height = 0;
 | |
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
 | |
|         width += bmp->GetWidth();
 | |
|         height = std::max<size_t>(height, bmp->GetHeight());
 | |
|     }
 | |
| 
 | |
| #ifdef BROKEN_ALPHA
 | |
| 
 | |
|     wxImage image(width, height);
 | |
|     image.InitAlpha();
 | |
|     // Fill in with a white color.
 | |
|     memset(image.GetData(), 0x0ff, width * height * 3);
 | |
|     // Fill in with full transparency.
 | |
|     memset(image.GetAlpha(),    0, width * height);
 | |
|     size_t x = 0;
 | |
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
 | |
|         if (bmp->GetWidth() > 0) {
 | |
|             if (bmp->GetDepth() == 32) {
 | |
|                 wxAlphaPixelData data(*const_cast<wxBitmap*>(bmp));
 | |
|                 //FIXME The following method is missing from wxWidgets 3.1.1.
 | |
|                 // It looks like the wxWidgets 3.0.3 called the wrapped bitmap's UseAlpha().
 | |
|                 //data.UseAlpha();
 | |
|                 if (data) {
 | |
|                     for (int r = 0; r < bmp->GetHeight(); ++ r) {
 | |
|                         wxAlphaPixelData::Iterator src(data);
 | |
|                         src.Offset(data, 0, r);
 | |
|                         unsigned char *dst_pixels = image.GetData()  + (x + r * width) * 3;
 | |
|                         unsigned char *dst_alpha  = image.GetAlpha() +  x + r * width;
 | |
|                         for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) {
 | |
|                             *dst_pixels ++ = src.Red();
 | |
|                             *dst_pixels ++ = src.Green();
 | |
|                             *dst_pixels ++ = src.Blue();
 | |
|                             *dst_alpha  ++ = src.Alpha();
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             } else if (bmp->GetDepth() == 24) {
 | |
|                 wxNativePixelData data(*const_cast<wxBitmap*>(bmp));
 | |
|                 if (data) {
 | |
|                     for (int r = 0; r < bmp->GetHeight(); ++ r) {
 | |
|                         wxNativePixelData::Iterator src(data);
 | |
|                         src.Offset(data, 0, r);
 | |
|                         unsigned char *dst_pixels = image.GetData()  + (x + r * width) * 3;
 | |
|                         unsigned char *dst_alpha  = image.GetAlpha() +  x + r * width;
 | |
|                         for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) {
 | |
|                             *dst_pixels ++ = src.Red();
 | |
|                             *dst_pixels ++ = src.Green();
 | |
|                             *dst_pixels ++ = src.Blue();
 | |
|                             *dst_alpha  ++ = wxALPHA_OPAQUE;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         x += bmp->GetWidth();
 | |
|     }
 | |
|     return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
 | |
| 
 | |
| #else
 | |
| 
 | |
|     wxBitmap *bitmap = this->insert(bitmap_key, width, height);
 | |
|     wxMemoryDC memDC;
 | |
|     memDC.SelectObject(*bitmap);
 | |
|     memDC.SetBackground(*wxTRANSPARENT_BRUSH);
 | |
|     memDC.Clear();
 | |
|     size_t x = 0;
 | |
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
 | |
|         if (bmp->GetWidth() > 0)
 | |
|             memDC.DrawBitmap(*bmp, x, 0, true);
 | |
|         x += bmp->GetWidth();
 | |
|     }
 | |
|     memDC.SelectObject(wxNullBitmap);
 | |
|     return bitmap;
 | |
| 
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 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);
 | |
|     image.InitAlpha();
 | |
|     unsigned char* imgdata = image.GetData();
 | |
|     unsigned char* imgalpha = image.GetAlpha();
 | |
|     for (size_t i = 0; i < width * height; ++ i) {
 | |
|         *imgdata ++ = r;
 | |
|         *imgdata ++ = g;
 | |
|         *imgdata ++ = b;
 | |
|         *imgalpha ++ = transparency;
 | |
|     }
 | |
|     return wxImage_to_wxBitmap_with_alpha(std::move(image));
 | |
| }
 | |
| 
 | |
| } // namespace GUI
 | |
| } // namespace Slic3r
 | 
