← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/remove_cached_resizing into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/remove_cached_resizing into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/remove_cached_resizing/+merge/243584

Suggested commit message:

- Remove ImageTransformations::resize(). This is now done on the fly by the GPU, this is just as fast and more memory efficient.
- Removes the dependency to sdl_gfx and all mentions of it in the project.
- Buttons and tab panels will now shrink images to fit in their drawing area. This exposes some overly big graphics we use in some places.
- Increase the size of the buildings in the BuildGrid preview from 34 pixels to 50. I think that looks much nicer
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/remove_cached_resizing into lp:widelands.
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2014-11-12 21:01:23 +0000
+++ CMakeLists.txt	2014-12-03 19:38:51 +0000
@@ -44,7 +44,6 @@
 find_package(OpenGL REQUIRED)
 find_package(PNG REQUIRED)
 find_package(SDL2 REQUIRED)
-find_package(SDL2_gfx REQUIRED)
 find_package(SDL2_image REQUIRED)
 find_package(SDL2_mixer REQUIRED)
 find_package(SDL2_net REQUIRED)

=== removed file 'cmake/Modules/FindSDL2_gfx.cmake'
--- cmake/Modules/FindSDL2_gfx.cmake	2014-10-13 15:04:50 +0000
+++ cmake/Modules/FindSDL2_gfx.cmake	1970-01-01 00:00:00 +0000
@@ -1,60 +0,0 @@
-# Locate SDL2_gfx library
-# This module defines
-# SDL2GFX_LIBRARY, the name of the library to link against
-# SDL2GFX_FOUND, if false, do not try to link to SDL2
-# SDL2GFX_INCLUDE_DIR, where to find SDL2/SDL.h
-#
-# $SDLDIR is an environment variable that would
-# correspond to the ./configure --prefix=$SDL2DIR
-# used in building SDL2.
-#
-# Created by Eric Wing. This was influenced by the FindSDL.cmake 
-# module, but with modifications to recognize OS X frameworks and 
-# additional Unix paths (FreeBSD, etc).
-
-FIND_PATH(SDL2GFX_INCLUDE_DIR SDL2_framerate.h 
-  SDL2_gfxPrimitives.h 
-  SDL2_imageFilter.h SDL2_rotozoom.h
-  HINTS
-  $ENV{SDL2GFXDIR}
-  $ENV{SDL2DIR}
-  PATH_SUFFIXES include SDL2
-  PATHS
-  ~/Library/Frameworks
-  /Library/Frameworks
-  /usr/local/include/SDL2
-  /usr/include/SDL2
-  /usr/local/include
-  /usr/include
-  /sw/include/SDL2 # Fink
-  /sw/include
-  /opt/local/include/SDL2 # DarwinPorts
-  /opt/local/include
-  /opt/csw/include/SDL2 # Blastwave
-  /opt/csw/include 
-  /opt/include/SDL2
-  /opt/include
-)
-
-FIND_LIBRARY(SDL2GFX_LIBRARY 
-  NAMES SDL2_gfx
-  HINTS
-  $ENV{SDL2GFXDIR}
-  $ENV{SDL2DIR}
-  PATH_SUFFIXES lib64 lib
-  PATHS
-  ~/Library/Frameworks
-  /Library/Frameworks
-  /usr/local
-  /usr
-  /sw
-  /opt/local
-  /opt/csw
-  /opt
-)
-
-SET(SDL2GFX_FOUND "NO")
-IF(SDL2GFX_LIBRARY AND SDL2GFX_INCLUDE_DIR)
-  SET(SDL2GFX_FOUND "YES")
-ENDIF(SDL2GFX_LIBRARY AND SDL2GFX_INCLUDE_DIR)
-

=== modified file 'cmake/WlFunctions.cmake'
--- cmake/WlFunctions.cmake	2014-11-12 20:12:48 +0000
+++ cmake/WlFunctions.cmake	2014-12-03 19:38:51 +0000
@@ -10,7 +10,6 @@
     USES_OPENGL
     USES_PNG
     USES_SDL2
-    USES_SDL2_GFX
     USES_SDL2_IMAGE
     USES_SDL2_MIXER
     USES_SDL2_NET
@@ -118,11 +117,6 @@
     target_link_libraries(${NAME} ${SDL2IMAGE_LIBRARY})
   endif()
 
-  if(ARG_USES_SDL2_GFX)
-    wl_include_system_directories(${NAME} ${SDL2GFX_INCLUDE_DIR})
-    target_link_libraries(${NAME} ${SDL2GFX_LIBRARY})
-  endif()
-
   if(ARG_USES_SDL2_TTF)
     wl_include_system_directories(${NAME} ${SDL2TTF_INCLUDE_DIR})
     target_link_libraries(${NAME} ${SDL2TTF_LIBRARY})

=== modified file 'src/editor/ui_menus/categorized_item_selection_menu.h'
--- src/editor/ui_menus/categorized_item_selection_menu.h	2014-10-14 06:30:20 +0000
+++ src/editor/ui_menus/categorized_item_selection_menu.h	2014-12-03 19:38:51 +0000
@@ -122,15 +122,7 @@
 			horizontal->add_space(kSpacing);
 			++nitems_handled;
 		}
-
-		const Image* category_picture = category.picture();
-		const int kCategoryImageSize = 24;
-		if (category_picture->width() > kCategoryImageSize ||
-		    category_picture->height() > kCategoryImageSize) {
-			category_picture =
-			   ImageTransformations::resize(category_picture, kCategoryImageSize, kCategoryImageSize);
-		}
-		tab_panel->add(category.name(), category_picture, vertical, category.descname());
+		tab_panel->add(category.name(), category.picture(), vertical, category.descname());
 	}
 	add(&current_selection_names_, UI::Align_Center, true);
 }

=== modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc'
--- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-11-27 21:29:21 +0000
+++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-12-03 19:38:51 +0000
@@ -76,44 +76,55 @@
 
 		const Texture& terrain_texture = terrain_descr.get_texture(0);
 		Texture* texture = new Texture(terrain_texture.width(), terrain_texture.height());
-		texture->blit(Point(0, 0),
+		texture->blit(Rect(0, 0, terrain_texture.width(), terrain_texture.height()),
 		              &terrain_texture,
 		              Rect(0, 0, terrain_texture.width(), terrain_texture.height()));
 		Point pt(1, terrain_texture.height() - kSmallPicHeight - 1);
 
 		if (ter_is == TerrainDescription::GREEN) {
-			texture->blit(pt, green->texture(), Rect(0, 0, green->width(), green->height()));
+			texture->blit(Rect(pt.x, pt.y, green->width(), green->height()),
+			              green->texture(),
+			              Rect(0, 0, green->width(), green->height()));
 			pt.x += kSmallPicWidth + 1;
 			/** TRANSLATORS: This is a terrain type tooltip in the editor */
 			tooltips.push_back(_("arable"));
 		} else {
 			if (ter_is & TerrainDescription::WATER) {
-				texture->blit(pt, water->texture(), Rect(0, 0, water->width(), water->height()));
+				texture->blit(Rect(pt.x, pt.y, water->width(), water->height()),
+				              water->texture(),
+				              Rect(0, 0, water->width(), water->height()));
 				pt.x += kSmallPicWidth + 1;
 				/** TRANSLATORS: This is a terrain type tooltip in the editor */
 				tooltips.push_back(_("aquatic"));
 			}
 			else if (ter_is & TerrainDescription::MOUNTAIN) {
-				texture->blit(pt, mountain->texture(), Rect(0, 0, mountain->width(), mountain->height()));
+				texture->blit(Rect(pt.x, pt.y, mountain->width(), mountain->height()),
+				              mountain->texture(),
+				              Rect(0, 0, mountain->width(), mountain->height()));
 				pt.x += kSmallPicWidth + 1;
 				/** TRANSLATORS: This is a terrain type tooltip in the editor */
 				tooltips.push_back(_("mountainous"));
 			}
 			if (ter_is & TerrainDescription::ACID) {
-				texture->blit(pt, dead->texture(), Rect(0, 0, dead->width(), dead->height()));
+				texture->blit(Rect(pt.x, pt.y, dead->width(), dead->height()),
+				              dead->texture(),
+				              Rect(0, 0, dead->width(), dead->height()));
 				pt.x += kSmallPicWidth + 1;
 				/** TRANSLATORS: This is a terrain type tooltip in the editor */
 				tooltips.push_back(_("dead"));
 			}
 			if (ter_is & TerrainDescription::UNPASSABLE) {
-				texture->blit(
-				   pt, unpassable->texture(), Rect(0, 0, unpassable->width(), unpassable->height()));
+				texture->blit(Rect(pt.x, pt.y, unpassable->width(), unpassable->height()),
+				              unpassable->texture(),
+				              Rect(0, 0, unpassable->width(), unpassable->height()));
 				pt.x += kSmallPicWidth + 1;
 				/** TRANSLATORS: This is a terrain type tooltip in the editor */
 				tooltips.push_back(_("unpassable"));
 			}
 			if (ter_is & TerrainDescription::DRY) {
-				texture->blit(pt, dry->texture(), Rect(0, 0, dry->width(), dry->height()));
+				texture->blit(Rect(pt.x, pt.y, dry->width(), dry->height()),
+				              dry->texture(),
+				              Rect(0, 0, dry->width(), dry->height()));
 				/** TRANSLATORS: This is a terrain type tooltip in the editor */
 				 tooltips.push_back(_("treeless"));
 			}

=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2014-12-01 21:28:21 +0000
+++ src/graphic/CMakeLists.txt	2014-12-03 19:38:51 +0000
@@ -131,7 +131,6 @@
     wordwrap.h
   USES_OPENGL
   USES_SDL2
-  USES_SDL2_GFX
   USES_SDL2_TTF
   DEPENDS
     base_exceptions

=== modified file 'src/graphic/animation.cc'
--- src/graphic/animation.cc	2014-11-28 16:40:55 +0000
+++ src/graphic/animation.cc	2014-12-03 19:38:51 +0000
@@ -323,7 +323,7 @@
 	assert(target);
 
 	const Image& frame = get_frame(time, clr);
-	target->blit(dst, frame.texture(), srcrc);
+	target->blit(Rect(dst.x, dst.y, srcrc.w, srcrc.h), frame.texture(), srcrc);
 }
 
 const Image& NonPackedAnimation::get_frame(uint32_t time, const RGBColor* playercolor) const {

=== modified file 'src/graphic/image_transformations.cc'
--- src/graphic/image_transformations.cc	2014-11-26 19:53:52 +0000
+++ src/graphic/image_transformations.cc	2014-12-03 19:38:51 +0000
@@ -22,7 +22,6 @@
 #include <string>
 
 #include <SDL.h>
-#include <SDL2_rotozoom.h>
 #include <boost/format.hpp>
 
 #include "base/macros.h"
@@ -77,79 +76,6 @@
 }
 
 /**
- * Produces a resized version of the specified image
- */
-Texture* resize_surface(Texture* src, uint32_t w, uint32_t h) {
-	assert(w != src->width() || h != src->height());
-
-	// First step: compute scaling factors
-	Rect srcrect = Rect(Point(0, 0), src->width(), src->height());
-
-	// Second step: get source material
-	SDL_Surface * srcsdl = extract_sdl_surface(*src, srcrect);
-	bool free_source = true;
-
-	// If we actually shrink a texture, ballpark the zoom so that the shrinking
-	// effect is weakened.
-	int factor = 1;
-	while ((static_cast<double>(w) * factor / srcsdl->w) < 1. ||
-	       (static_cast<double>(h) * factor / srcsdl->h) < 1.) {
-		++factor;
-	}
-	if (factor > 2) {
-		SDL_Surface* temp = shrinkSurface(srcsdl, factor - 1, factor - 1);
-		if (free_source) {
-			SDL_FreeSurface(srcsdl);
-		}
-		srcsdl = temp;
-		free_source = true;
-	}
-
-	// Third step: perform the zoom and placement
-	SDL_Surface* zoomed = zoomSurface(srcsdl, double(w) / srcsdl->w, double(h) / srcsdl->h, 1);
-
-	if (free_source)
-		SDL_FreeSurface(srcsdl);
-
-	if (uint32_t(zoomed->w) != w || uint32_t(zoomed->h) != h) {
-		const SDL_PixelFormat & fmt = *zoomed->format;
-		SDL_Surface * placed = SDL_CreateRGBSurface
-			(SDL_SWSURFACE, w, h,
-			 fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask);
-		SDL_Rect srcrc =
-			{0, 0,
-			 static_cast<uint16_t>(zoomed->w), static_cast<uint16_t>(zoomed->h)
-			};  // For some reason SDL_Surface and SDL_Rect express w,h in different types
-		SDL_Rect dstrc = {0, 0, 0, 0};
-		SDL_SetSurfaceAlphaMod(zoomed,  SDL_ALPHA_TRANSPARENT);
-		SDL_SetSurfaceBlendMode(zoomed, SDL_BLENDMODE_NONE);
-		SDL_BlitSurface(zoomed, &srcrc, placed, &dstrc); // Updates dstrc
-
-		uint32_t fillcolor = SDL_MapRGBA(zoomed->format, 0, 0, 0, 255);
-
-		if (zoomed->w < placed->w) {
-			dstrc.x = zoomed->w;
-			dstrc.y = 0;
-			dstrc.w = placed->w - zoomed->w;
-			dstrc.h = zoomed->h;
-			SDL_FillRect(placed, &dstrc, fillcolor);
-		}
-		if (zoomed->h < placed->h) {
-			dstrc.x = 0;
-			dstrc.y = zoomed->h;
-			dstrc.w = placed->w;
-			dstrc.h = placed->h - zoomed->h;
-			SDL_FillRect(placed, &dstrc, fillcolor);
-		}
-
-		SDL_FreeSurface(zoomed);
-		zoomed = placed;
-	}
-
-	return new Texture(zoomed);
-}
-
-/**
  * Create a grayed version of the given texture.
  */
 Texture* gray_out_texture(Texture* texture) {
@@ -320,31 +246,6 @@
 	TextureCache* const texture_cache_;  // not owned
 };
 
-// A resized copy of an Image.
-class ResizedImage : public TransformedImage {
-public:
-	ResizedImage
-		(const string& ghash, const Image& original,
-		 TextureCache* texture_cache, uint16_t w, uint16_t h)
-		: TransformedImage(ghash, original, texture_cache), w_(w), h_(h) {
-			assert(w != original.width() || h != original.height());
-	}
-	virtual ~ResizedImage() {}
-
-	// Overwrites TransformedImage.
-	uint16_t width() const override {return w_;}
-	uint16_t height() const override {return h_;}
-
-	// Implements TransformedImage.
-	Texture* recalculate_texture() const override {
-		Texture* rv = resize_surface(original_.texture(), w_, h_);
-		return rv;
-	}
-
-private:
-	uint16_t w_, h_;
-};
-
 // A grayed out copy of an Image.
 class GrayedOutImage : public TransformedImage {
 public:
@@ -419,17 +320,6 @@
 		}
 }
 
-const Image* resize(const Image* original, uint16_t w, uint16_t h) {
-	if (original->width() == w && original->height() == h)
-		return original;
-
-	const string new_hash = (boost::format("%s:%i:%i") % original->hash() % w % h).str();
-	if (g_gr->images().has(new_hash))
-		return g_gr->images().get(new_hash);
-	return
-		g_gr->images().insert(new ResizedImage(new_hash, *original, &g_gr->textures(), w, h));
-}
-
 const Image* gray_out(const Image* original) {
 	const string new_hash = original->hash() + ":greyed_out";
 	if (g_gr->images().has(new_hash))

=== modified file 'src/graphic/image_transformations.h'
--- src/graphic/image_transformations.h	2014-07-05 16:41:51 +0000
+++ src/graphic/image_transformations.h	2014-12-03 19:38:51 +0000
@@ -37,9 +37,6 @@
 // safe to call the methods with the same arguments multiple times without
 // construction cost.
 
-// Returns a resized image of the original.
-const Image* resize(const Image* original, uint16_t w, uint16_t h);
-
 // Returns a grayed out image of the original.
 const Image* gray_out(const Image* original);
 

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2014-11-30 17:11:22 +0000
+++ src/graphic/rendertarget.cc	2014-12-03 19:38:51 +0000
@@ -163,19 +163,22 @@
  * Blits a Image on another Surface
  *
  * This blit function copies the pixels to the destination surface.
- * If the source surface contains a alpha channel this is used during
- * the blit.
  */
 void RenderTarget::blit(const Point& dst, const Image* image, BlendMode blend_mode, UI::Align align)
 {
-	Point dstpoint(dst);
+	Point destination_point(dst);
 
-	UI::correct_for_align(align, image->width(), image->height(), &dstpoint);
+	UI::correct_for_align(align, image->width(), image->height(), &destination_point);
 
 	Rect srcrc(Point(0, 0), image->width(), image->height());
 
-	if (to_surface_geometry(&dstpoint, &srcrc))
-		m_surface->blit(dstpoint, image->texture(), srcrc, blend_mode);
+	if (to_surface_geometry(&destination_point, &srcrc)) {
+		m_surface->blit(
+		   Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h),
+		   image->texture(),
+		   srcrc,
+		   blend_mode);
+	}
 }
 
 /**
@@ -194,9 +197,28 @@
 	           std::min<int32_t>(image->width() - gsrcrc.x, gsrcrc.w),
 	           std::min<int32_t>(image->height() - gsrcrc.y, gsrcrc.h));
 
-	Point dstpt(dst);
-	if (to_surface_geometry(&dstpt, &srcrc))
-		m_surface->blit(dstpt, image->texture(), srcrc, blend_mode);
+	Point destination_point(dst);
+	if (to_surface_geometry(&destination_point, &srcrc))
+		m_surface->blit(
+		   Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h),
+		   image->texture(),
+		   srcrc,
+		   blend_mode);
+}
+
+void RenderTarget::blitrect_scale(const Rect& dst,
+                                  const Image* image,
+                                  const Rect& src,
+                                  const BlendMode blend_mode) {
+
+	Point destination_point(dst.x, dst.y);
+	Rect srcrect(src);
+	if (to_surface_geometry(&destination_point, &srcrect)) {
+		m_surface->blit(Rect(destination_point.x, destination_point.y, dst.w, dst.h),
+		                image->texture(),
+		                src,
+		                blend_mode);
+	}
 }
 
 /**
@@ -251,7 +273,8 @@
 				if (tx + srcrc.w > r.w)
 					srcrc.w = r.w - tx;
 
-				m_surface->blit(r.top_left() + Point(tx, ty), image->texture(), srcrc, blend_mode);
+				const Rect dst_rect(r.x + tx, r.y + ty, srcrc.w, srcrc.h);
+				m_surface->blit(dst_rect, image->texture(), srcrc, blend_mode);
 
 				tx += srcrc.w;
 
@@ -283,12 +306,12 @@
 {
 	const Animation& anim = g_gr->animations().get_animation(animation);
 
-	Point dstpt = dst - anim.hotspot();
+	Point destination_point = dst - anim.hotspot();
 
 	Rect srcrc(Point(0, 0), anim.width(), anim.height());
 
-	if (to_surface_geometry(&dstpt, &srcrc))
-		anim.blit(time, dstpt, srcrc, player ? &player->get_playercolor() : NULL, m_surface);
+	if (to_surface_geometry(&destination_point, &srcrc))
+		anim.blit(time, destination_point, srcrc, player ? &player->get_playercolor() : NULL, m_surface);
 
 	//  Look if there is a sound effect registered for this frame and trigger
 	//  the effect (see SoundHandler::stereo_position).
@@ -303,13 +326,13 @@
 {
 	const Animation& anim = g_gr->animations().get_animation(animation);
 
-	Point dstpt = dst - anim.hotspot();
-	dstpt += gsrcrc.top_left();
+	Point destination_point = dst - anim.hotspot();
+	destination_point += gsrcrc.top_left();
 
 	Rect srcrc(gsrcrc);
 
-	if (to_surface_geometry(&dstpt, &srcrc))
-		anim.blit(time, dstpt, srcrc, player ? &player->get_playercolor() : NULL, m_surface);
+	if (to_surface_geometry(&destination_point, &srcrc))
+		anim.blit(time, destination_point, srcrc, player ? &player->get_playercolor() : NULL, m_surface);
 }
 
 /**

=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h	2014-11-24 07:25:21 +0000
+++ src/graphic/rendertarget.h	2014-12-03 19:38:51 +0000
@@ -49,6 +49,8 @@
  * \note If the sub-window would be empty/invisible, \ref enter_window() returns
  * false and doesn't change the window state at all.
 */
+// TODO(sirver): remove window functions and merge with surface once
+// the old richtext renderer is gone.
 class RenderTarget {
 public:
 	RenderTarget(Surface*);
@@ -74,6 +76,12 @@
 	              const Rect& src,
 	              BlendMode blend_mode = BlendMode::UseAlpha);
 
+	void blitrect_scale(
+			const Rect& dst,
+			const Image* image,
+			const Rect& src,
+			BlendMode blend_mode = BlendMode::UseAlpha);
+
 	void tile(const Rect&,
 	          const Image* image,
 	          const Point& ofs,

=== modified file 'src/graphic/surface.cc'
--- src/graphic/surface.cc	2014-11-27 20:31:39 +0000
+++ src/graphic/surface.cc	2014-12-03 19:38:51 +0000
@@ -158,7 +158,7 @@
 }
 
 void Surface::blit
-	(const Point& dst, const Texture* texture, const Rect& srcrc, BlendMode blend_mode)
+	(const Rect& dst, const Texture* texture, const Rect& srcrc, BlendMode blend_mode)
 {
 	glViewport(0, 0, width(), height());
 
@@ -188,7 +188,8 @@
 		gl_src_rect.h = y2 - y1;
 	}
 
-	const FloatRect gl_dst_rect = to_opengl(Rect(dst.x, dst.y, srcrc.w, srcrc.h), ConversionMode::kExact);
+	const FloatRect gl_dst_rect =
+	   to_opengl(Rect(dst.x, dst.y, dst.w, dst.h), ConversionMode::kExact);
 
 	BlitProgram::instance().draw(gl_dst_rect, gl_src_rect, texture->get_gl_texture(), blend_mode);
 }

=== modified file 'src/graphic/surface.h'
--- src/graphic/surface.h	2014-11-24 07:25:21 +0000
+++ src/graphic/surface.h	2014-12-03 19:38:51 +0000
@@ -43,7 +43,7 @@
 	uint16_t height() const;
 
 	/// This draws a part of another surface to this surface
-	virtual void blit(const Point&,
+	virtual void blit(const Rect& dst,
 	                  const Texture*,
 	                  const Rect& srcrc,
 	                  BlendMode blend_mode = BlendMode::UseAlpha);

=== modified file 'src/graphic/text/CMakeLists.txt'
--- src/graphic/text/CMakeLists.txt	2014-11-23 10:13:14 +0000
+++ src/graphic/text/CMakeLists.txt	2014-12-03 19:38:51 +0000
@@ -16,7 +16,6 @@
     textstream.h
   USES_SDL2
   USES_SDL2_TTF
-  USES_SDL2_GFX
   DEPENDS
     graphic_sdl_utils
     base_exceptions

=== modified file 'src/graphic/text/rt_render.cc'
--- src/graphic/text/rt_render.cc	2014-11-24 07:25:21 +0000
+++ src/graphic/text/rt_render.cc	2014-12-03 19:38:51 +0000
@@ -333,7 +333,10 @@
 Texture* TextNode::render(TextureCache* texture_cache) {
 	const Texture& img = m_font.render(m_txt, m_s.font_color, m_s.font_style, texture_cache);
 	Texture* rv = new Texture(img.width(), img.height());
-	rv->blit(Point(0, 0), &img, Rect(0, 0, img.width(), img.height()), BlendMode::Copy);
+	rv->blit(Rect(0, 0, img.width(), img.height()),
+	         &img,
+	         Rect(0, 0, img.width(), img.height()),
+	         BlendMode::Copy);
 	return rv;
 }
 
@@ -361,7 +364,7 @@
 	Texture* rv = new Texture(m_w, m_h);
 	for (uint16_t curx = 0; curx < m_w; curx += t.width()) {
 		Rect srcrect(Point(0, 0), min<int>(t.width(), m_w - curx), m_h);
-		rv->blit(Point(curx, 0), &t, srcrect, BlendMode::Copy);
+		rv->blit(Rect(curx, 0, srcrect.w, srcrect.h), &t, srcrect, BlendMode::Copy);
 	}
 	return rv;
 }
@@ -423,13 +426,13 @@
 
 		// Draw background image (tiling)
 		if (m_bg) {
-			Point dst;
+			Rect dst;
 			Rect srcrect(Point(0, 0), 1, 1);
 			for (uint16_t curx = 0; curx < m_w; curx += m_bg->width()) {
 				dst.x = curx;
 				dst.y = 0;
-				srcrect.w = min<int>(m_bg->width(), m_w - curx);
-				srcrect.h = m_h;
+				srcrect.w = dst.w = min<int>(m_bg->width(), m_w - curx);
+				srcrect.h = dst.h = m_h;
 				rv->blit(dst, m_bg->texture(), srcrect, BlendMode::Copy);
 			}
 		} else {
@@ -482,14 +485,15 @@
 
 		// Draw background image (tiling)
 		if (m_bg_img) {
-			Point dst;
+			Rect dst;
 			Rect src(0, 0, 0, 0);
 
 			for (uint16_t cury = m_margin.top; cury < m_h + m_margin.top; cury += m_bg_img->height()) {
 				for (uint16_t curx = m_margin.left; curx < m_w + m_margin.left; curx += m_bg_img->width()) {
-					dst.x = curx; dst.y = cury;
-					src.w = min<int>(m_bg_img->width(), m_w + m_margin.left - curx);
-					src.h = min<int>(m_bg_img->height(), m_h + m_margin.top - cury);
+					dst.x = curx;
+					dst.y = cury;
+					src.w = dst.w = min<int>(m_bg_img->width(), m_w + m_margin.left - curx);
+					src.h = dst.h = min<int>(m_bg_img->height(), m_h + m_margin.top - cury);
 					rv->blit(dst, m_bg_img->texture(), src, BlendMode::Copy);
 				}
 			}
@@ -499,7 +503,10 @@
 		for (RenderNode* n : m_nodes_to_render) {
 			Texture* node_texture = n->render(texture_cache);
 			if (node_texture) {
-				Point dst = Point(n->x() + m_margin.left, n->y() + m_margin.top);
+				Rect dst = Rect(n->x() + m_margin.left,
+				                n->y() + m_margin.top,
+				                node_texture->width(),
+				                node_texture->height());
 				Rect src = Rect(0, 0, node_texture->width(), node_texture->height());
 
 				rv->blit(dst, node_texture, src, set_alpha ? BlendMode::Copy : BlendMode::UseAlpha);
@@ -553,7 +560,10 @@
 
 Texture* ImgRenderNode::render(TextureCache* /* texture_cache */) {
 	Texture* rv = new Texture(m_image.width(), m_image.height());
-	rv->blit(Point(0, 0), m_image.texture(), Rect(0, 0, m_image.width(), m_image.height()), BlendMode::Copy);
+	rv->blit(Rect(0, 0, m_image.width(), m_image.height()),
+	         m_image.texture(),
+	         Rect(0, 0, m_image.width(), m_image.height()),
+	         BlendMode::Copy);
 	return rv;
 }
 // End: Helper Stuff

=== modified file 'src/graphic/texture.cc'
--- src/graphic/texture.cc	2014-12-01 06:06:41 +0000
+++ src/graphic/texture.cc	2014-12-03 19:38:51 +0000
@@ -265,7 +265,7 @@
 }
 
 void Texture::blit
-	(const Point& dst, const Texture* src, const Rect& srcrc, BlendMode blend_mode)
+	(const Rect& dst, const Texture* src, const Rect& srcrc, BlendMode blend_mode)
 {
 	if (m_w <= 0 || m_h <= 0) {
 		return;

=== modified file 'src/graphic/texture.h'
--- src/graphic/texture.h	2014-11-27 18:47:26 +0000
+++ src/graphic/texture.h	2014-12-03 19:38:51 +0000
@@ -58,7 +58,7 @@
 	void brighten_rect(const Rect&, int32_t factor) override;
 	virtual void draw_line
 		(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor&, uint8_t width) override;
-	void blit(const Point&,
+	void blit(const Rect& dstretc,
 	          const Texture*,
 	          const Rect& srcrc,
 	          BlendMode blend_mode = BlendMode::UseAlpha) override;

=== modified file 'src/graphic/texture_atlas.cc'
--- src/graphic/texture_atlas.cc	2014-11-28 09:02:24 +0000
+++ src/graphic/texture_atlas.cc	2014-12-03 19:38:51 +0000
@@ -141,9 +141,10 @@
 	});
 
 	for (Block& block : blocks_) {
-		packed_texture->blit(block.node->r.top_left(),
-		                     block.texture,
-		                     Rect(0, 0, block.texture->width(), block.texture->height()));
+		packed_texture->blit(
+		   Rect(block.node->r.x, block.node->r.y, block.texture->width(), block.texture->height()),
+		   block.texture,
+		   Rect(0, 0, block.texture->width(), block.texture->height()));
 		textures->emplace_back(new Texture(
 		   packed_texture->get_gl_texture(),
 		   Rect(block.node->r.top_left(), block.texture->width(), block.texture->height()),

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2014-11-22 11:32:06 +0000
+++ src/ui_basic/button.cc	2014-12-03 19:38:51 +0000
@@ -32,6 +32,9 @@
 
 namespace UI {
 
+// Margin around image. The image will be scaled down to fit into this rectangle with preserving size.
+constexpr int kButtonImageMargin = 2;
+
 Button::Button //  for textual buttons
 	(Panel * const parent,
 	 const std::string & name,
@@ -169,16 +172,19 @@
 
 	//  if we got a picture, draw it centered
 	if (m_pic_custom) {
-		uint16_t cpw = m_pic_custom->width();
-		uint16_t cph = m_pic_custom->height();
+		const int max_image_w = get_w() - 2 * kButtonImageMargin;
+		const int max_image_h = get_h() - 2 * kButtonImageMargin;
+		double image_scale =
+		   std::min(1.,
+		            std::min(static_cast<double>(max_image_w) / m_pic_custom->width(),
+		                     static_cast<double>(max_image_h) / m_pic_custom->height()));
+		int blit_width = image_scale * m_pic_custom->width();
+		int blit_height = image_scale * m_pic_custom->height();
 
-		//  ">> 1" is almost like "/ 2", but simpler for signed types (difference
-		//  is that -1 >> 1 is -1 but -1 / 2 is 0).
-		dst.blit
-			(Point
-			 	((get_w() - static_cast<int32_t>(cpw)) >> 1,
-			 	 (get_h() - static_cast<int32_t>(cph)) >> 1),
-			 m_enabled ? m_pic_custom : m_pic_custom_disabled);
+		dst.blitrect_scale(
+		   Rect((get_w() - blit_width) / 2, (get_h() - blit_height) / 2, blit_width, blit_height),
+		   m_enabled ? m_pic_custom : m_pic_custom_disabled,
+		   Rect(0, 0, m_pic_custom->width(), m_pic_custom->height()));
 
 	} else if (m_title.length()) {
 		//  otherwise draw title string centered

=== modified file 'src/ui_basic/icon.cc'
--- src/ui_basic/icon.cc	2014-11-22 10:18:20 +0000
+++ src/ui_basic/icon.cc	2014-12-03 19:38:51 +0000
@@ -54,13 +54,18 @@
 	m_draw_frame = false;
 }
 
-
-
 void Icon::draw(RenderTarget & dst) {
 	if (m_pic) {
-		int32_t w = (get_w() - m_pic->width()) / 2;
-		int32_t h = (get_h() - m_pic->height()) / 2;
-		dst.blit(Point(w, h), m_pic);
+		double scale = std::min(static_cast<double>(get_w()) / m_pic->width(),
+		                        static_cast<double>(get_h()) / m_pic->height());
+		scale = std::min(1., scale);
+
+		int width = scale * get_w();
+		int height = scale * get_h();
+		int x = (get_w() - width) / 2;
+		int y = (get_h() - height) / 2;
+		dst.blitrect_scale(
+		   Rect(x, y, width, height), m_pic, Rect(0, 0, m_pic->width(), m_pic->height()));
 	}
 	if (m_draw_frame) {
 		dst.draw_rect(Rect(0, 0, get_w(), get_h()), m_framecolor);

=== modified file 'src/ui_basic/icon.h'
--- src/ui_basic/icon.h	2014-09-19 09:07:14 +0000
+++ src/ui_basic/icon.h	2014-12-03 19:38:51 +0000
@@ -26,7 +26,8 @@
 namespace UI {
 
 /**
- * A simple icon drawn in the center of the area
+ * A simple icon drawn in the center of the area. If the image is
+ * bigger than the icon, the image will be scaled to fit.
 */
 struct Icon : public Panel {
 	Icon

=== modified file 'src/ui_basic/progresswindow.cc'
--- src/ui_basic/progresswindow.cc	2014-11-28 16:40:55 +0000
+++ src/ui_basic/progresswindow.cc	2014-12-03 19:38:51 +0000
@@ -27,7 +27,6 @@
 #include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/graphic.h"
-#include "graphic/image_transformations.h"
 #include "graphic/rendertarget.h"
 #include "io/filesystem/layered_filesystem.h"
 #include "wui/text_constants.h"
@@ -42,10 +41,7 @@
 
 namespace UI {
 
-ProgressWindow::ProgressWindow(const std::string & background)
-	: m_xres(0), m_yres(0),
-	m_background_pic(nullptr)
-{
+ProgressWindow::ProgressWindow(const std::string& background) {
 	set_background(background);
 	step(_("Preparing..."));
 }
@@ -63,22 +59,15 @@
 	m_label_center.y = yres * PROGRESS_LABEL_POSITION_Y / 100;
 	Rect wnd_rect(Point(0, 0), xres, yres);
 
-	if (!m_background_pic || xres != m_xres || yres != m_yres) {
-		// (Re-)Load background graphics
-		m_background_pic = ImageTransformations::resize(g_gr->images().get(m_background), xres, yres);
-
-		const uint32_t h = g_fh->get_fontheight (UI_FONT_SMALL);
-		m_label_rectangle.x = xres / 4;
-		m_label_rectangle.w = xres / 2;
-		m_label_rectangle.y =
-		m_label_center.y - h / 2 - PROGRESS_STATUS_RECT_PADDING;
-		m_label_rectangle.h = h + 2 * PROGRESS_STATUS_RECT_PADDING;
-		// remember last resolution
-		m_xres = xres;
-		m_yres = yres;
-	}
-
-	rt.blit(Point(0, 0), m_background_pic);
+	const uint32_t h = g_fh->get_fontheight (UI_FONT_SMALL);
+	m_label_rectangle.x = xres / 4;
+	m_label_rectangle.w = xres / 2;
+	m_label_rectangle.y =
+	m_label_center.y - h / 2 - PROGRESS_STATUS_RECT_PADDING;
+	m_label_rectangle.h = h + 2 * PROGRESS_STATUS_RECT_PADDING;
+
+	const Image* bg = g_gr->images().get(m_background);
+	rt.blitrect_scale(Rect(0, 0, xres, yres), bg, Rect(0, 0, bg->width(), bg->height()));
 
 	Rect border_rect = m_label_rectangle;
 	border_rect.x -= PROGRESS_STATUS_BORDER_X;
@@ -97,7 +86,6 @@
 	} else {
 		m_background = "pics/progress.png";
 	}
-	m_background_pic = nullptr;
 	draw_background(rt, g_gr->get_xres(), g_gr->get_yres());
 	update(true);
 }

=== modified file 'src/ui_basic/progresswindow.h'
--- src/ui_basic/progresswindow.h	2014-09-14 11:31:58 +0000
+++ src/ui_basic/progresswindow.h	2014-12-03 19:38:51 +0000
@@ -62,13 +62,10 @@
 
 private:
 	using VisualizationArray = std::vector<IProgressVisualization *>;
-	uint32_t  m_xres;
-	uint32_t  m_yres;
 	Point m_label_center;
 	Rect  m_label_rectangle;
 	VisualizationArray m_visualizations;
 	std::string m_background;
-	const Image* m_background_pic;
 
 	void draw_background(RenderTarget & rt, uint32_t xres, uint32_t yres);
 	void update(bool repaint);

=== modified file 'src/ui_basic/tabpanel.cc'
--- src/ui_basic/tabpanel.cc	2014-09-10 14:48:40 +0000
+++ src/ui_basic/tabpanel.cc	2014-12-03 19:38:51 +0000
@@ -23,11 +23,15 @@
 #include "ui_basic/mouse_constants.h"
 
 namespace UI {
-#define TP_BUTTON_WIDTH     34
-#define TP_BUTTON_HEIGHT    34
+
+// Button size of tab buttons in pixels.
+constexpr int kTabPanelButtonSize = 34;
+
+// Margin around image. The image will be scaled down to fit into this rectangle with preserving size.
+constexpr int kTabPanelImageMargin = 2;
 
 //  height of the bar separating buttons and tab contents
-#define TP_SEPARATOR_HEIGHT  4
+constexpr int kTabPanelSeparatorHeight = 4;
 
 /*
  * =================
@@ -43,8 +47,8 @@
 	 Panel             * const gpanel)
 	:
 	NamedPanel
-		(parent, name, id * TP_BUTTON_WIDTH, 0, TP_BUTTON_WIDTH,
-		 TP_BUTTON_HEIGHT, gtooltip),
+		(parent, name, id * kTabPanelButtonSize, 0, kTabPanelButtonSize,
+		 kTabPanelButtonSize, gtooltip),
 	m_parent(parent),
 	m_id(id),
 	pic(gpic),
@@ -102,7 +106,7 @@
 		uint32_t h = get_h();
 
 		// avoid excessive craziness in case there is a wraparound
-		h = std::min(h, h - (TP_BUTTON_HEIGHT + TP_SEPARATOR_HEIGHT));
+		h = std::min(h, h - (kTabPanelButtonSize + kTabPanelSeparatorHeight));
 		panel->set_size(get_w(), h);
 	}
 }
@@ -116,8 +120,8 @@
 	uint32_t h;
 
 	// size of button row
-	w = TP_BUTTON_WIDTH * m_tabs.size();
-	h = TP_BUTTON_HEIGHT + TP_SEPARATOR_HEIGHT;
+	w = kTabPanelButtonSize * m_tabs.size();
+	h = kTabPanelButtonSize + kTabPanelSeparatorHeight;
 
 	// size of contents
 	if (m_active < m_tabs.size()) {
@@ -156,7 +160,7 @@
 	uint32_t id = m_tabs.size();
 	m_tabs.push_back(new Tab(this, id, name, pic, tooltip_text, panel));
 
-	panel->set_pos(Point(0, TP_BUTTON_HEIGHT + TP_SEPARATOR_HEIGHT));
+	panel->set_pos(Point(0, kTabPanelButtonSize + kTabPanelSeparatorHeight));
 	panel->set_visible(id == m_active);
 	update_desired_size();
 
@@ -202,70 +206,81 @@
 	uint32_t x;
 
 	// draw the background
-	static_assert(2 < TP_BUTTON_WIDTH, "assert(2 < TP_BUTTON_WIDTH) failed.");
-	static_assert(4 < TP_BUTTON_HEIGHT, "assert(4 < TP_BUTTON_HEIGHT) failed.");
+	static_assert(2 < kTabPanelButtonSize, "assert(2 < kTabPanelButtonSize) failed.");
+	static_assert(4 < kTabPanelButtonSize, "assert(4 < kTabPanelButtonSize) failed.");
 
 	if (m_pic_background) {
 		dst.tile
-			(Rect(Point(0, 0), m_tabs.size() * TP_BUTTON_WIDTH, TP_BUTTON_HEIGHT - 2),
+			(Rect(Point(0, 0), m_tabs.size() * kTabPanelButtonSize, kTabPanelButtonSize - 2),
 			 m_pic_background, Point(get_x(), get_y()));
-		assert(TP_BUTTON_HEIGHT - 2 <= get_h());
+		assert(kTabPanelButtonSize - 2 <= get_h());
 		dst.tile
 			(Rect
-			 (Point(0, TP_BUTTON_HEIGHT - 2),
-			  get_w(), get_h() - TP_BUTTON_HEIGHT + 2),
+			 (Point(0, kTabPanelButtonSize - 2),
+			  get_w(), get_h() - kTabPanelButtonSize + 2),
 			 m_pic_background,
-			 Point(get_x(), get_y() + TP_BUTTON_HEIGHT - 2));
+			 Point(get_x(), get_y() + kTabPanelButtonSize - 2));
 	}
 
 	// draw the buttons
-	for (idx = 0, x = 0; idx < m_tabs.size(); idx++, x += TP_BUTTON_WIDTH) {
+	for (idx = 0, x = 0; idx < m_tabs.size(); idx++, x += kTabPanelButtonSize) {
 		if (m_highlight == static_cast<int32_t>(idx))
 			dst.brighten_rect
-				(Rect(Point(x, 0), TP_BUTTON_WIDTH, TP_BUTTON_HEIGHT),
+				(Rect(Point(x, 0), kTabPanelButtonSize, kTabPanelButtonSize),
 				 MOUSE_OVER_BRIGHT_FACTOR);
 
 		// Draw the icon
 		assert(m_tabs[idx]->pic);
-		uint16_t cpw = m_tabs[idx]->pic->width();
-		uint16_t cph = m_tabs[idx]->pic->height();
-		dst.blit
-			(Point(x + (TP_BUTTON_WIDTH - cpw) / 2, (TP_BUTTON_HEIGHT - cph) / 2),
-			 m_tabs[idx]->pic);
+
+		// Scale the image down if needed, but keep the ratio.
+		constexpr int kMaxImageSize = kTabPanelButtonSize - 2 * kTabPanelImageMargin;
+		double image_scale =
+		   std::min(1.,
+		            std::min(static_cast<double>(kMaxImageSize) / m_tabs[idx]->pic->width(),
+		                     static_cast<double>(kMaxImageSize) / m_tabs[idx]->pic->height()));
+
+		uint16_t picture_width = image_scale * m_tabs[idx]->pic->width();
+		uint16_t picture_height = image_scale * m_tabs[idx]->pic->height();
+		dst.blitrect_scale(Rect(x + (kTabPanelButtonSize - picture_width) / 2,
+		                        (kTabPanelButtonSize - picture_height) / 2,
+		                        picture_width,
+		                        picture_height),
+		                   m_tabs[idx]->pic,
+		                   Rect(0, 0, m_tabs[idx]->pic->width(), m_tabs[idx]->pic->height()));
 
 		// Draw top part of border
 		RGBColor black(0, 0, 0);
 
 		dst.brighten_rect
-			(Rect(Point(x, 0), TP_BUTTON_WIDTH, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+			(Rect(Point(x, 0), kTabPanelButtonSize, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		dst.brighten_rect
-			(Rect(Point(x, 2), 2, TP_BUTTON_HEIGHT - 4),
+			(Rect(Point(x, 2), 2, kTabPanelButtonSize - 4),
 			 BUTTON_EDGE_BRIGHT_FACTOR);
 		dst.fill_rect
-			(Rect(Point(x + TP_BUTTON_WIDTH - 2, 2), 1, TP_BUTTON_HEIGHT - 4),
+			(Rect(Point(x + kTabPanelButtonSize - 2, 2), 1, kTabPanelButtonSize - 4),
 			 black);
 		dst.fill_rect
-			(Rect(Point(x + TP_BUTTON_WIDTH - 1, 1), 1, TP_BUTTON_HEIGHT - 3),
+			(Rect(Point(x + kTabPanelButtonSize - 1, 1), 1, kTabPanelButtonSize - 3),
 			 black);
 
 		// Draw bottom part
 		if (m_active != idx)
 			dst.brighten_rect
-				(Rect(Point(x, TP_BUTTON_HEIGHT - 2), TP_BUTTON_WIDTH, 2),
+				(Rect(Point(x, kTabPanelButtonSize - 2), kTabPanelButtonSize, 2),
 				 2 * BUTTON_EDGE_BRIGHT_FACTOR);
 		else {
 			dst.brighten_rect
-				(Rect(Point(x, TP_BUTTON_HEIGHT - 2), 2, 2),
+				(Rect(Point(x, kTabPanelButtonSize - 2), 2, 2),
 				 BUTTON_EDGE_BRIGHT_FACTOR);
 
 			dst.brighten_rect
-				(Rect(Point(x + TP_BUTTON_WIDTH - 2, TP_BUTTON_HEIGHT - 2), 2, 2),
+				(Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 2), 2, 2),
 				 2 * BUTTON_EDGE_BRIGHT_FACTOR);
 			dst.fill_rect
-				(Rect(Point(x + TP_BUTTON_WIDTH - 2, TP_BUTTON_HEIGHT - 1), 1, 1),
+				(Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 1), 1, 1),
 				 black);
 			dst.fill_rect
-				(Rect(Point(x + TP_BUTTON_WIDTH - 2, TP_BUTTON_HEIGHT - 2), 2, 1),
+				(Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 2), 2, 1),
 				 black);
 		}
 	}
@@ -273,7 +288,7 @@
 	// draw the remaining separator
 	assert(x <= static_cast<uint32_t>(get_w()));
 	dst.brighten_rect
-		(Rect(Point(x, TP_BUTTON_HEIGHT - 2), get_w() - x, 2),
+		(Rect(Point(x, kTabPanelButtonSize - 2), get_w() - x, 2),
 		 2 * BUTTON_EDGE_BRIGHT_FACTOR);
 }
 
@@ -285,7 +300,7 @@
 {
 	if (!inside && m_highlight >= 0) {
 		update
-			(m_highlight * TP_BUTTON_WIDTH, 0, TP_BUTTON_WIDTH, TP_BUTTON_HEIGHT);
+			(m_highlight * kTabPanelButtonSize, 0, kTabPanelButtonSize, kTabPanelButtonSize);
 
 		m_highlight = -1;
 	}
@@ -300,10 +315,10 @@
 {
 	int32_t hl;
 
-	if (y < 0 || y >= TP_BUTTON_HEIGHT)
+	if (y < 0 || y >= kTabPanelButtonSize)
 		hl = -1;
 	else {
-		hl = x / TP_BUTTON_WIDTH;
+		hl = x / kTabPanelButtonSize;
 
 		if (m_tabs.size() <= static_cast<size_t>(hl))
 			hl = -1;
@@ -316,11 +331,11 @@
 		}
 		if (m_highlight >= 0)
 			update
-				(m_highlight * TP_BUTTON_WIDTH, 0,
-				 TP_BUTTON_WIDTH, TP_BUTTON_HEIGHT);
+				(m_highlight * kTabPanelButtonSize, 0,
+				 kTabPanelButtonSize, kTabPanelButtonSize);
 		if (hl >= 0)
 			update
-				(hl * TP_BUTTON_WIDTH, 0, TP_BUTTON_WIDTH, TP_BUTTON_HEIGHT);
+				(hl * kTabPanelButtonSize, 0, kTabPanelButtonSize, kTabPanelButtonSize);
 
 		m_highlight = hl;
 	}
@@ -335,10 +350,10 @@
 	if (btn == SDL_BUTTON_LEFT) {
 		int32_t id;
 
-		if (y >= TP_BUTTON_HEIGHT)
+		if (y >= kTabPanelButtonSize)
 			return false;
 
-		id = x / TP_BUTTON_WIDTH;
+		id = x / kTabPanelButtonSize;
 
 		if (static_cast<size_t>(id) < m_tabs.size()) {
 			activate(id);

=== modified file 'src/ui_fsmenu/base.cc'
--- src/ui_fsmenu/base.cc	2014-11-30 10:11:09 +0000
+++ src/ui_fsmenu/base.cc	2014-12-03 19:38:51 +0000
@@ -27,7 +27,6 @@
 #include "base/wexception.h"
 #include "graphic/font.h"
 #include "graphic/graphic.h"
-#include "graphic/image_transformations.h"
 #include "graphic/rendertarget.h"
 #include "io/filesystem/filesystem.h"
 #include "profile/profile.h"
@@ -49,15 +48,12 @@
  */
 FullscreenMenuBase::FullscreenMenuBase(char const* const bgpic)
    : UI::Panel(nullptr, 0, 0, g_gr->get_xres(), g_gr->get_yres()) {
-	// Load background graphics
-	const std::string bgpicpath = (boost::format("pics/%s") % bgpic).str();
-	background_ = ImageTransformations::resize(g_gr->images().get(bgpicpath), get_w(), get_h());
-
 	textstyle_small_ = UI::TextStyle::ui_small();
 	textstyle_small_.font = UI::Font::get(ui_fn(), fs_small());
 
 	textstyle_big_ = UI::TextStyle::ui_big();
 	textstyle_big_.font = UI::Font::get(ui_fn(), fs_big());
+	background_image_ = (boost::format("pics/%s") % bgpic).str();
 }
 
 FullscreenMenuBase::~FullscreenMenuBase()
@@ -69,7 +65,8 @@
  * Draw the background / splash screen
 */
 void FullscreenMenuBase::draw(RenderTarget & dst) {
-	dst.blit(Point(0, 0), background_);
+	const Image* bg = g_gr->images().get(background_image_);
+	dst.blitrect_scale(Rect(0, 0, get_w(), get_h()), bg, Rect(0, 0, bg->width(), bg->height()));
 }
 
 uint32_t FullscreenMenuBase::fs_small() {

=== modified file 'src/ui_fsmenu/base.h'
--- src/ui_fsmenu/base.h	2014-11-30 10:11:09 +0000
+++ src/ui_fsmenu/base.h	2014-12-03 19:38:51 +0000
@@ -53,7 +53,7 @@
 private:
 	UI::TextStyle textstyle_big_;
 	UI::TextStyle textstyle_small_;
-	const Image* background_;
+	std::string background_image_;
 };
 
 

=== modified file 'src/ui_fsmenu/loadgame.cc'
--- src/ui_fsmenu/loadgame.cc	2014-11-24 07:10:03 +0000
+++ src/ui_fsmenu/loadgame.cc	2014-12-03 19:38:51 +0000
@@ -334,11 +334,6 @@
 					if (scale > 1.0) scale = 1.0; // Don't make the image too big; fuzziness will result
 					uint16_t w = scale * m_minimap_image->width();
 					uint16_t h = scale * m_minimap_image->height();
-					const Image* resized = ImageTransformations::resize(m_minimap_image.get(), w, h);
-					// keeps our in_memory_image around and give to icon the one
-					// from resize that is handled by the cache. It is still linked to our
-					// texture.
-					m_minimap_icon.set_size(w, h);
 
 					// Center the minimap in the available space
 					int32_t xpos = m_right_column_x + (get_w() - m_right_column_margin - w - m_right_column_x) / 2;
@@ -351,10 +346,11 @@
 						ypos += (m_minimap_h - h) / 2;
 					}
 
+					m_minimap_icon.set_size(w, h);
 					m_minimap_icon.set_pos(Point(xpos, ypos));
 					m_minimap_icon.set_frame(UI_FONT_CLR_FG);
 					m_minimap_icon.set_visible(true);
-					m_minimap_icon.set_icon(resized);
+					m_minimap_icon.set_icon(m_minimap_image.get());
 				} catch (const std::exception & e) {
 					log("Failed to load the minimap image : %s\n", e.what());
 				}

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2014-11-30 18:49:38 +0000
+++ src/wui/fieldaction.cc	2014-12-03 19:38:51 +0000
@@ -52,11 +52,7 @@
 using Widelands::EditorGameBase;
 using Widelands::Game;
 
-#define BG_CELL_WIDTH  34 // extents of one cell
-#define BG_CELL_HEIGHT 34
-
-//sizes for the images in the build menu (containing building icons)
-#define BUILDMENU_IMAGE_SIZE 30. // used for width and height
+constexpr int kBuildGridCellSize = 50;
 
 // The BuildGrid presents a selection of buildable buildings
 struct BuildGrid : public UI::IconGrid {
@@ -86,7 +82,7 @@
 BuildGrid::BuildGrid(
 		UI::Panel* parent, const RGBColor& player_color, const Widelands::TribeDescr& tribe,
 		int32_t x, int32_t y, int32_t cols) :
-	UI::IconGrid(parent, x, y, BG_CELL_WIDTH, BG_CELL_HEIGHT, cols),
+	UI::IconGrid(parent, x, y, kBuildGridCellSize, kBuildGridCellSize, cols),
 	player_color_(player_color),
 	tribe_(tribe)
 {
@@ -104,17 +100,13 @@
 {
 	const Widelands::BuildingDescr & descr =
 		*tribe_.get_building_descr(Widelands::BuildingIndex(id));
-	const Image& anim_frame = g_gr->animations().get_animation(descr.get_animation("idle"))
-		.representative_image(player_color_);
-	const uint16_t image_w = anim_frame.width();
-	const uint16_t image_h = anim_frame.height();
-	double ratio = BUILDMENU_IMAGE_SIZE / std::max(image_w, image_h);
-	const Image* menu_image = ImageTransformations::resize(&anim_frame, image_w * ratio, image_h * ratio);
-	UI::IconGrid::add
-		(descr.name(), menu_image,
-		 reinterpret_cast<void *>(id),
-		 descr.descname() + "<br><font size=11>" + _("Construction costs:") + "</font><br>" +
-			waremap_to_richtext(tribe_, descr.buildcost()));
+	UI::IconGrid::add(
+	   descr.name(),
+	   &g_gr->animations().get_animation(descr.get_animation("idle")).representative_image(
+	      player_color_),
+	   reinterpret_cast<void*>(id),
+	   descr.descname() + "<br><font size=11>" + _("Construction costs:") + "</font><br>" +
+	      waremap_to_richtext(tribe_, descr.buildcost()));
 }
 
 
@@ -329,7 +321,7 @@
 
 	// Now force the mouse onto the first button
 	set_mouse_pos
-		(Point(17 + BG_CELL_WIDTH * m_best_tab, m_fastclick ? 51 : 17));
+		(Point(17 + kBuildGridCellSize * m_best_tab, m_fastclick ? 51 : 17));
 
 	// Will only do something if we explicitly set another fast click panel
 	// than the first button

=== modified file 'utils/win32/mingw/Makefile'
--- utils/win32/mingw/Makefile	2014-03-01 12:35:59 +0000
+++ utils/win32/mingw/Makefile	2014-12-03 19:38:51 +0000
@@ -107,7 +107,7 @@
 OBJECT_DIR:=../../$(TARGET)-$(BUILD)
 CFLAGS:=-Wall $(shell $(SDL_CONFIG) --cflags) $(ADD_CFLAGS)
 CXXFLAGS:=$(CFLAGS)
-LDFLAGS:=$(shell $(SDL_CONFIG) --libs) icon.o $(ADD_LDFLAGS) -lz -lpng -lSDL_image -lSDL_mixer -lSDL_ttf -lSDL_net -lSDL_gfx -lwsock32 -llua
+LDFLAGS:=$(shell $(SDL_CONFIG) --libs) icon.o $(ADD_LDFLAGS) -lz -lpng -lSDL_image -lSDL_mixer -lSDL_ttf -lSDL_net -lwsock32 -llua
 
 ##############################################################################
 # Building


Follow ups