From ab7ab9e52ab87963831f90ab25957d883878654d Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Thu, 2 Jun 2016 21:00:37 +0200
Subject: New ImageCache class for reusing Image resources.

---
 plugingui/Makefile.mingw32 |   1 +
 plugingui/image.cc         |  32 +++++++++++++-
 plugingui/image.h          |  11 +++--
 plugingui/imagecache.cc    | 104 +++++++++++++++++++++++++++++++++++++++++++++
 plugingui/imagecache.h     |  72 +++++++++++++++++++++++++++++++
 5 files changed, 216 insertions(+), 4 deletions(-)
 create mode 100644 plugingui/imagecache.cc
 create mode 100644 plugingui/imagecache.h

(limited to 'plugingui')

diff --git a/plugingui/Makefile.mingw32 b/plugingui/Makefile.mingw32
index 9820d1a..98d8f29 100644
--- a/plugingui/Makefile.mingw32
+++ b/plugingui/Makefile.mingw32
@@ -35,6 +35,7 @@ GUI_SRC = \
 	filebrowser.cc \
 	directory.cc \
 	image.cc \
+	imagecache.cc \
 	combobox.cc \
 	progressbar.cc \
 	verticalline.cc \
diff --git a/plugingui/image.cc b/plugingui/image.cc
index 250dc60..63f708d 100644
--- a/plugingui/image.cc
+++ b/plugingui/image.cc
@@ -48,9 +48,39 @@ Image::Image(const std::string& filename)
 	load(rc.data(), rc.size());
 }
 
+Image::Image(Image&& other)
+	: _width(other._width)
+	, _height(other._height)
+	, image_data(other.image_data)
+{
+	other.image_data = nullptr;
+	other._width = 0;
+	other._height = 0;
+}
+
 Image::~Image()
 {
-	std::free(image_data);
+	if(image_data)
+	{
+		std::free(image_data);
+	}
+}
+
+Image& Image::operator=(Image&& other)
+{
+	if(image_data)
+	{
+		std::free(image_data);
+	}
+	image_data = other.image_data;
+	_width = other._width;
+	_height = other._height;
+
+	other.image_data = nullptr;
+	other._width = 0;
+	other._height = 0;
+
+	return *this;
 }
 
 void Image::setError()
diff --git a/plugingui/image.h b/plugingui/image.h
index 92bd181..8d1fd59 100644
--- a/plugingui/image.h
+++ b/plugingui/image.h
@@ -33,12 +33,16 @@
 
 namespace GUI {
 
-class Image {
+class Image
+{
 public:
 	Image(const char* data, size_t size);
 	Image(const std::string& filename);
+	Image(Image&& other);
 	~Image();
 
+	Image& operator=(Image&& other);
+
 	size_t width() const;
 	size_t height() const;
 
@@ -49,8 +53,9 @@ private:
 
 	void load(const char* data, size_t size);
 
-	size_t _width, _height;
-	unsigned char* image_data;
+	std::size_t _width{0};
+	std::size_t _height{0};
+	unsigned char* image_data{nullptr};
 };
 
 } // GUI::
diff --git a/plugingui/imagecache.cc b/plugingui/imagecache.cc
new file mode 100644
index 0000000..6ce1171
--- /dev/null
+++ b/plugingui/imagecache.cc
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ *            imagecache.cc
+ *
+ *  Thu Jun  2 17:12:05 CEST 2016
+ *  Copyright 2016 Bent Bisballe Nyeng
+ *  deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ *  This file is part of DrumGizmo.
+ *
+ *  DrumGizmo is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  DrumGizmo is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with DrumGizmo; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+#include "imagecache.h"
+
+#include <cassert>
+
+#include "image.h"
+
+namespace GUI
+{
+
+ScopedImageBorrower::ScopedImageBorrower(ImageCache& imageCache,
+                                         const std::string& filename)
+	: imageCache(imageCache)
+	, filename(filename)
+	, image(imageCache.borrow(filename))
+{
+}
+
+ScopedImageBorrower::ScopedImageBorrower(ScopedImageBorrower&& other)
+	: imageCache(other.imageCache)
+	, filename(other.filename)
+	, image(other.image)
+{
+	other.filename.clear();
+}
+
+ScopedImageBorrower::~ScopedImageBorrower()
+{
+	if(!filename.empty())
+	{
+		imageCache.giveBack(filename);
+	}
+}
+
+Image& ScopedImageBorrower::operator*()
+{
+	return image;
+}
+
+Image& ScopedImageBorrower::operator()()
+{
+	return image;
+}
+
+ScopedImageBorrower ImageCache::getImage(const std::string& filename)
+{
+	return ScopedImageBorrower(*this, filename);
+}
+
+Image& ImageCache::borrow(const std::string& filename)
+{
+	auto cacheIterator = imageCache.find(filename);
+	if(cacheIterator == imageCache.end())
+	{
+		Image image(filename);
+		auto insertValue =
+			imageCache.emplace(filename,
+			                   std::move(std::make_pair(0, std::move(image))));
+		cacheIterator = insertValue.first;
+	}
+
+	auto& cacheEntry = cacheIterator->second;
+	++cacheEntry.first;
+	return cacheEntry.second;
+}
+
+void ImageCache::giveBack(const std::string& filename)
+{
+	auto cacheIterator = imageCache.find(filename);
+	assert(cacheIterator != imageCache.end());
+	auto& cacheEntry = cacheIterator->second;
+	--cacheEntry.first;
+	if(cacheEntry.first == 0)
+	{
+		imageCache.erase(cacheIterator);
+	}
+}
+
+} // GUI::
diff --git a/plugingui/imagecache.h b/plugingui/imagecache.h
new file mode 100644
index 0000000..9ca28fb
--- /dev/null
+++ b/plugingui/imagecache.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ *            imagecache.h
+ *
+ *  Thu Jun  2 17:12:05 CEST 2016
+ *  Copyright 2016 Bent Bisballe Nyeng
+ *  deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ *  This file is part of DrumGizmo.
+ *
+ *  DrumGizmo is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  DrumGizmo is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with DrumGizmo; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+#pragma once
+
+#include <string>
+#include <map>
+#include <utility>
+
+namespace GUI
+{
+
+class Image;
+class ImageCache;
+
+class ScopedImageBorrower
+{
+public:
+	ScopedImageBorrower(ImageCache& imageCache, const std::string& filename);
+	ScopedImageBorrower(ScopedImageBorrower&& other);
+	~ScopedImageBorrower();
+
+	ScopedImageBorrower& operator=(ScopedImageBorrower&& other);
+
+	Image& operator*();
+	Image& operator()();
+
+private:
+	ImageCache& imageCache;
+	std::string filename;
+	Image& image;
+};
+
+class ImageCache
+{
+public:
+	ScopedImageBorrower getImage(const std::string& filename);
+
+private:
+	friend class ScopedImageBorrower;
+
+	Image& borrow(const std::string& filename);
+	void giveBack(const std::string& filename);
+
+protected:
+	std::map<std::string, std::pair<std::size_t, Image>> imageCache;
+};
+
+} // GUI::
-- 
cgit v1.2.3