changeset 1:6bc25027c198

Client: do not use std::shared_ptr anymore
author David Demelier <markand@malikania.fr>
date Tue, 22 Mar 2016 21:15:41 +0100
parents 8991989c4708
children 2418900a1cc5
files CMakeLists.txt libclient/malikania/Animation.h libclient/malikania/Animator.cpp libclient/malikania/Animator.h libclient/malikania/ClientResourcesLoader.cpp libclient/malikania/ClientResourcesLoader.h libclient/malikania/backend/sdl/WindowSdl.cpp tests/libclient/animation/main.cpp
diffstat 8 files changed, 280 insertions(+), 293 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Mar 22 18:26:05 2016 +0100
+++ b/CMakeLists.txt	Tue Mar 22 21:15:41 2016 +0100
@@ -26,6 +26,8 @@
 	"${malikania_SOURCE_DIR}/cmake/packages"
 )
 
+set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+
 include(cmake/MalikaniaOptions.cmake)
 include(cmake/MalikaniaFunctions.cmake)
 include(cmake/MalikaniaVersion.cmake)
--- a/libclient/malikania/Animation.h	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/Animation.h	Tue Mar 22 21:15:41 2016 +0100
@@ -69,6 +69,11 @@
 };
 
 /**
+ * @brief List of frames.
+ */
+using AnimationFrames = std::vector<AnimationFrame>;
+
+/**
  * @class Animation
  * @brief Animation description.
  *
@@ -83,22 +88,20 @@
  */
 class Animation {
 private:
-	std::shared_ptr<Sprite> m_sprite;
-	std::vector<AnimationFrame> m_frames;
+	Sprite m_sprite;
+	AnimationFrames m_frames;
 
 public:
 	/**
 	 * Create an animation.
 	 *
-	 * @pre sprite must not be null
 	 * @param sprite the sprite image
 	 * @param frames the frames to show
 	 */
-	Animation(std::shared_ptr<Sprite> sprite, std::vector<AnimationFrame> frames) noexcept
+	inline Animation(Sprite sprite, AnimationFrames frames) noexcept
 		: m_sprite(std::move(sprite))
 		, m_frames(std::move(frames))
 	{
-		assert(m_sprite);
 	}
 
 	/**
@@ -106,7 +109,17 @@
 	 *
 	 * @return the sprite
 	 */
-	inline const std::shared_ptr<Sprite> &sprite() const noexcept
+	inline const Sprite &sprite() const noexcept
+	{
+		return m_sprite;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the sprite
+	 */
+	inline Sprite &sprite() noexcept
 	{
 		return m_sprite;
 	}
@@ -116,7 +129,7 @@
 	 *
 	 * @return the frames
 	 */
-	inline const std::vector<AnimationFrame> &frames() const noexcept
+	inline const AnimationFrames &frames() const noexcept
 	{
 		return m_frames;
 	}
--- a/libclient/malikania/Animator.cpp	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/Animator.cpp	Tue Mar 22 21:15:41 2016 +0100
@@ -16,28 +16,25 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <cassert>
-
 #include "Animation.h"
 #include "Animator.h"
 
 namespace malikania {
 
-Animator::Animator(std::shared_ptr<Animation> animation) noexcept
-	: m_animation(std::move(animation))
+Animator::Animator(Animation &animation) noexcept
+	: m_animation(animation)
 {
-	assert(m_animation);
 }
 
 void Animator::update() noexcept
 {
-	unsigned total = m_animation->sprite()->rows() * m_animation->sprite()->columns();
+	unsigned total = m_animation.sprite().rows() * m_animation.sprite().columns();
 
 	if (m_current >= total) {
 		return;
 	}
 
-	if (m_timer.elapsed() >= (*m_animation)[m_current].delay()) {
+	if (m_timer.elapsed() >= m_animation[m_current].delay()) {
 		m_current ++;
 		m_timer.reset();
 	}
@@ -46,11 +43,11 @@
 void Animator::draw(Window &window, const Point &point)
 {
 	// TODO: assert ?
-	if (m_current >= m_animation->sprite()->rows() * m_animation->sprite()->columns()) {
+	if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns()) {
 		return;
 	}
 
-	m_animation->sprite()->draw(window, m_current, point);
+	m_animation.sprite().draw(window, m_current, point);
 }
 
 } // !malikania
--- a/libclient/malikania/Animator.h	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/Animator.h	Tue Mar 22 21:15:41 2016 +0100
@@ -40,7 +40,7 @@
  */
 class Animator {
 private:
-	std::shared_ptr<Animation> m_animation;
+	Animation &m_animation;
 	ElapsedTimer m_timer;
 	unsigned m_current{0};
 
@@ -51,7 +51,7 @@
 	 * @pre animation must not be null
 	 * @param animation the animation
 	 */
-	Animator(std::shared_ptr<Animation> animation) noexcept;
+	Animator(Animation &animation) noexcept;
 
 	/**
 	 * Update the animator state.
--- a/libclient/malikania/ClientResourcesLoader.cpp	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/ClientResourcesLoader.cpp	Tue Mar 22 21:15:41 2016 +0100
@@ -88,8 +88,7 @@
 		throw std::runtime_error(id + ": not a JSON object");
 	}
 
-	// TODO: return all resources as shared_ptr or make a cache for sprites.
-	std::shared_ptr<Sprite> sprite = std::make_shared<Sprite>(loadSprite(requireString(id, value, "sprite")));
+	Sprite sprite = loadSprite(requireString(id, value, "sprite"));
 
 	/* Load all frames */
 	json::Value property = value["frames"];
@@ -98,7 +97,7 @@
 		throw std::runtime_error(id + ": missing 'frames' property (array expected)");
 	}
 
-	std::vector<AnimationFrame> frames;
+	AnimationFrames frames;
 
 	for (auto it = property.begin(); it != property.end(); ++it) {
 		if (!it->isObject()) {
--- a/libclient/malikania/ClientResourcesLoader.h	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/ClientResourcesLoader.h	Tue Mar 22 21:15:41 2016 +0100
@@ -21,12 +21,13 @@
 
 #include <malikania/ResourcesLoader.h>
 
+#include "Animation.h"
+#include "Image.h"
+#include "Size.h"
+#include "Sprite.h"
+
 namespace malikania {
 
-class Animation;
-class Image;
-class Size;
-class Sprite;
 class Window;
 
 /**
--- a/libclient/malikania/backend/sdl/WindowSdl.cpp	Tue Mar 22 18:26:05 2016 +0100
+++ b/libclient/malikania/backend/sdl/WindowSdl.cpp	Tue Mar 22 21:15:41 2016 +0100
@@ -1,265 +1,240 @@
-/*
- * WindowSdl.cpp -- window object (SDL2 implementation)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdexcept>
-
-#include <malikania/Window.h>
-
-namespace malikania {
-
-WindowSdl::WindowSdl(unsigned width, unsigned height)
-	: m_window(nullptr, nullptr)
-	, m_renderer(nullptr, nullptr)
-{
-	SDL_SetMainReady();
-	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
-
-	m_window = WindowHandle(
-		SDL_CreateWindow("Malikania", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL),
-		SDL_DestroyWindow
-	);
-
-	if (m_window == nullptr) {
-		throw std::runtime_error(SDL_GetError());
-	}
-
-	// Create renderer
-	m_renderer = RendererHandle(
-		SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
-		SDL_DestroyRenderer
-	);
-
-	if (m_renderer == nullptr) {
-		throw std::runtime_error(SDL_GetError());
-	}
-
-	if (TTF_Init() == -1) {
-		throw std::runtime_error(TTF_GetError());
-	}
-}
-
-void WindowSdl::processEvents(Window &window)
-{
-	SDL_Event event;
-
-	while (SDL_PollEvent(&event)) {
-		switch (event.type) {
-		case SDL_KEYUP:
-			window.onKeyUp(event.key.keysym.sym);
-			break;
-		// TODO continue implemanting all event possible
-		case SDL_KEYDOWN:
-			window.onKeyDown(event.key.keysym.sym);
-			break;
-		case SDL_QUIT:
-			window.close();
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-void WindowSdl::clear()
-{
-	SDL_RenderClear(m_renderer.get());
-}
-
-void WindowSdl::update()
-{
-	// TO AUDIT
-#if 0
-	for (Refresh function : m_refreshList) {
-		function();
-	}
-#endif
-}
-
-void WindowSdl::present()
-{
-	SDL_RenderPresent(m_renderer.get());
-}
-
-Size WindowSdl::resolution()
-{
-	SDL_DisplayMode current;
-	int width = 0;
-	int height = 0;
-	for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
-		int error = SDL_GetCurrentDisplayMode(i, &current);
-		if (error == 0) {
-			// Get the last one
-			// TODO test with only one display mode, but we have to test with more than that
-			width = current.w;
-			height = current.h;
-		} else {
-			throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
-		}
-	}
-
-	return Size((unsigned)width, (unsigned)height);
-}
-
-void WindowSdl::setDrawingColor(const Color &color)
-{
-	int error = SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't set drawing color" + std::string(SDL_GetError()));
-	}
-}
-
-void WindowSdl::drawLine(const Line &line)
-{
-	int error = SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw line" + std::string(SDL_GetError()));
-	}
-}
-
-void WindowSdl::drawLines(const std::vector<Point> &points)
-{
-	SDL_Point sdlPoints[points.size()];
-
-	int i = 0;
-	for (const Point &point : points) {
-		sdlPoints[i++] = {(int)point.x(), (int)point.y()};
-	}
-
-	int error = SDL_RenderDrawLines(m_renderer.get(), sdlPoints, points.size());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw lines" + std::string(SDL_GetError()));
-	}
-}
-
-void WindowSdl::drawPoint(const Point &point)
-{
-	int error = SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw point" + std::string(SDL_GetError()));
-	}
-}
-
-void WindowSdl::drawPoints(const std::vector<Point> &points)
-{
-	SDL_Point sdlPoints[points.size()];
-
-	int i = 0;
-	for (const Point &point : points) {
-		sdlPoints[i++] = {point.x(), point.y()};
-	}
-
-	int error = SDL_RenderDrawPoints(m_renderer.get(), sdlPoints, points.size());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw points" + std::string(SDL_GetError()));
-	}
-}
-
-void WindowSdl::drawRectangle(const Rectangle &rectangle, bool filled, const malikania::Color &fillColor)
-{
-	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
-	int error = SDL_RenderDrawRect(m_renderer.get(), &rect);
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw rectangle" + std::string(SDL_GetError()));
-	}
-	if (filled) {
-		this->setDrawingColor(fillColor);
-		error = SDL_RenderFillRect(m_renderer.get(), &rect);
-		if (error != 0) {
-			throw std::runtime_error("Couldn't fill rectangle" + std::string(SDL_GetError()));
-		}
-	}
-}
-
-void WindowSdl::drawRectangles(const std::vector<Rectangle> &rectangles, bool filled, std::vector<Color> fillColors)
-{
-	SDL_Rect sdlRects[rectangles.size()];
-
-	int i = 0;
-	for (const Rectangle &rectangle : rectangles) {
-		sdlRects[i++] = {rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
-	}
-
-	int error = SDL_RenderDrawRects(m_renderer.get(), sdlRects, rectangles.size());
-	if (error != 0) {
-		throw std::runtime_error("Couldn't draw rectangles" + std::string(SDL_GetError()));
-	}
-
-	if (filled) {
-		if (rectangles.size() != fillColors.size()) {
-			throw std::runtime_error("Couldn't fill rectangles, rectangles size and fillColors size are not the same");
-		}
-		int j = 0;
-		for (Color fillColor : fillColors) {
-			this->setDrawingColor(fillColor);
-			error = SDL_RenderFillRect(m_renderer.get(), &sdlRects[j++]);
-			if (error != 0) {
-				throw std::runtime_error("Couldn't fill rectangle" + std::string(SDL_GetError()));
-			}
-		}
-	}
-}
-
-/**
- * TODO Add color in parameters
- * @brief WindowSdl::drawText
- * @param text
- * @param size
- */
-void WindowSdl::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
-{
-	SDL_Color textColor = {0, 0, 0, 255};
-	printf("LOL: %s\n", text.c_str());
-	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), textColor);
-	SDL_Texture* textTexture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
-#if 0
-	Size screenSize = resolution();
-	SDL_Rect screen{0, 0, (int)screenSize.width(), (int)screenSize.height()};
-#endif
-	SDL_RenderCopy(m_renderer.get(), textTexture, nullptr, &rect);
-
-	SDL_FreeSurface(message);
-}
-
-/**
- * TODO Add color in parameters
- * @brief WindowSdl::drawText
- * @param text
- * @param size
- */
-void WindowSdl::drawText(const std::string &text, Font &font, const Point &point)
-{
-	SDL_Color color = {0, 0, 0, 0};
-	SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
-	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
-	SDL_Texture* textTexture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-	SDL_Rect rect{point.x(), point.y(), message->w, message->h};
-#if 0
-	Size screenSize = resolution();
-	SDL_Rect screen{0, 0, (int)screenSize.width(), (int)screenSize.height()};
-#endif
-	SDL_RenderCopy(m_renderer.get(), textTexture, nullptr, &rect);
-
-	SDL_FreeSurface(message);
-}
-
-void WindowSdl::close()
-{
-}
-
-} // !malikania
+/*
+ * WindowSdl.cpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdexcept>
+
+#include <malikania/Window.h>
+
+namespace malikania {
+
+WindowSdl::WindowSdl(unsigned width, unsigned height)
+	: m_window(nullptr, nullptr)
+	, m_renderer(nullptr, nullptr)
+{
+	SDL_SetMainReady();
+	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+	m_window = WindowHandle(
+		SDL_CreateWindow("Malikania", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL),
+		SDL_DestroyWindow
+	);
+
+	if (m_window == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	// Create renderer
+	m_renderer = RendererHandle(
+		SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+		SDL_DestroyRenderer
+	);
+
+	if (m_renderer == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	if (TTF_Init() == -1) {
+		throw std::runtime_error(TTF_GetError());
+	}
+}
+
+void WindowSdl::processEvents(Window &window)
+{
+	SDL_Event event;
+
+	while (SDL_PollEvent(&event)) {
+		switch (event.type) {
+		case SDL_KEYUP:
+			window.onKeyUp(event.key.keysym.sym);
+			break;
+		// TODO continue implemanting all event possible
+		case SDL_KEYDOWN:
+			window.onKeyDown(event.key.keysym.sym);
+			break;
+		case SDL_QUIT:
+			window.close();
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void WindowSdl::clear()
+{
+	SDL_RenderClear(m_renderer.get());
+}
+
+void WindowSdl::update()
+{
+	// TO AUDIT
+#if 0
+	for (Refresh function : m_refreshList) {
+		function();
+	}
+#endif
+}
+
+void WindowSdl::present()
+{
+	SDL_RenderPresent(m_renderer.get());
+}
+
+Size WindowSdl::resolution()
+{
+	SDL_DisplayMode current;
+	int width = 0;
+	int height = 0;
+	for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
+		int error = SDL_GetCurrentDisplayMode(i, &current);
+		if (error == 0) {
+			// Get the last one
+			// TODO test with only one display mode, but we have to test with more than that
+			width = current.w;
+			height = current.h;
+		} else {
+			throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
+		}
+	}
+
+	return Size((unsigned)width, (unsigned)height);
+}
+
+void WindowSdl::setDrawingColor(const Color &color)
+{
+	int error = SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha());
+	if (error != 0) {
+		throw std::runtime_error("Couldn't set drawing color" + std::string(SDL_GetError()));
+	}
+}
+
+void WindowSdl::drawLine(const Line &line)
+{
+	if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void WindowSdl::drawLines(const std::vector<Point> &points)
+{
+	std::vector<SDL_Point> sdlPoints(points.size());
+
+	for (unsigned i = 0; i < points.size(); ++i) {
+		sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
+	}
+
+	if (SDL_RenderDrawLines(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void WindowSdl::drawPoint(const Point &point)
+{
+	if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void WindowSdl::drawPoints(const std::vector<Point> &points)
+{
+	std::vector<SDL_Point> sdlPoints(points.size());
+
+	for (unsigned i = 0; i < points.size(); ++i) {
+		sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
+	}
+
+	if (SDL_RenderDrawPoints(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+// TODO: not sure to keep this signature (add fillRect probably)
+void WindowSdl::drawRectangle(const Rectangle &rectangle, bool filled, const malikania::Color &fillColor)
+{
+	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+	int error = SDL_RenderDrawRect(m_renderer.get(), &rect);
+	if (error != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+	if (filled) {
+		this->setDrawingColor(fillColor);
+		error = SDL_RenderFillRect(m_renderer.get(), &rect);
+		if (error != 0) {
+			throw std::runtime_error(SDL_GetError());
+		}
+	}
+}
+
+// TODO: same as above
+void WindowSdl::drawRectangles(const std::vector<Rectangle> &rectangles, bool filled, std::vector<Color> fillColors)
+{
+	std::vector<SDL_Rect> sdlRects(rectangles.size());
+
+	for (unsigned i = 0; i < rectangles.size(); ++i) {
+		sdlRects[i] = SDL_Rect{rectangles[i].x(), rectangles[i].y(), (int)rectangles[i].width(), (int)rectangles[i].height()};
+	}
+
+	if (SDL_RenderDrawRects(m_renderer.get(), sdlRects.data(), sdlRects.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	if (filled) {
+		if (rectangles.size() != fillColors.size()) {
+			throw std::runtime_error("Couldn't fill rectangles, rectangles size and fillColors size are not the same");
+		}
+
+		int j = 0;
+		for (Color fillColor : fillColors) {
+			this->setDrawingColor(fillColor);
+
+			if (SDL_RenderFillRect(m_renderer.get(), &sdlRects[j++]) != 0) {
+				throw std::runtime_error("Couldn't fill rectangle" + std::string(SDL_GetError()));
+			}
+		}
+	}
+}
+
+// TODO: merge this into only one function and test results.
+void WindowSdl::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
+{
+	SDL_Color color = {0, 0, 0, 255};
+	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+	SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+
+	SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+	SDL_FreeSurface(message);
+}
+
+void WindowSdl::drawText(const std::string &text, Font &font, const Point &point)
+{
+	SDL_Color color = {0, 0, 0, 0};
+	SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
+	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+	SDL_Texture* textTexture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+	SDL_Rect rect{point.x(), point.y(), message->w, message->h};
+
+	SDL_RenderCopy(m_renderer.get(), textTexture, nullptr, &rect);
+	SDL_FreeSurface(message);
+}
+
+void WindowSdl::close()
+{
+}
+
+} // !malikania
--- a/tests/libclient/animation/main.cpp	Tue Mar 22 18:26:05 2016 +0100
+++ b/tests/libclient/animation/main.cpp	Tue Mar 22 21:15:41 2016 +0100
@@ -80,10 +80,10 @@
 
 	try {
 		Animation animation = m_loader.loadAnimation("animations/margins.json");
-		Animator animator(std::make_shared<Animation>(animation));
+		Animator animator(animation);
 
-		auto x = (400 / 2) - (animation.sprite()->cell().width() / 2);
-		auto y = (400 / 2) - (animation.sprite()->cell().height() / 2);
+		auto x = (400 / 2) - (animation.sprite().cell().width() / 2);
+		auto y = (400 / 2) - (animation.sprite().cell().height() / 2);
 
 		while (timer.elapsed() < 8000) {
 			window.clear();