← Back to team overview

widelands-dev team mailing list archive

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

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/rendertarget_ints into lp:widelands.

Commit message:
Use int values in RenderTarget and alignment functions where float precision is not needed.

- RenderTarget::draw_rect, RenderTarget::fill_rect, RenderTarget::brighten_rect, RenderTarget::blit, RenderTarget::blit_monochrome and RenderTarget::blitrect
- UI::correct_for_align and UI::center_vertically
- Consistently use UI::correct_for_align outside of RenderTarget.

Requested reviews:
  Widelands Developers (widelands-dev)

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

Use ints in RenderTarget everywhere except for scaled map elements and plot lines. This means no more hunting for fuzzy-looking GUI elements and text.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/rendertarget_ints into lp:widelands.
=== modified file 'src/graphic/font_handler.cc'
--- src/graphic/font_handler.cc	2017-02-28 20:07:07 +0000
+++ src/graphic/font_handler.cc	2017-04-22 16:16:31 +0000
@@ -54,9 +54,9 @@
 	int caret_x = style.calc_bare_width(text.substr(0, caret_offset));
 
 	const Image* caret_image = g_gr->images().get("images/ui_basic/caret.png");
-	Vector2f caretpt;
+	Vector2i caretpt;
 	caretpt.x = dstpoint.x + caret_x + LINE_MARGIN - caret_image->width();
-	caretpt.y = dstpoint.y + (style.font->height() - caret_image->height()) / 2.f;
+	caretpt.y = dstpoint.y + (style.font->height() - caret_image->height()) / 2;
 	dst.blit(caretpt, caret_image);
 }
 
@@ -203,7 +203,7 @@
  */
 void FontHandler::draw_text(RenderTarget& dst,
                             const TextStyle& style,
-                            Vector2i dstpoint_i,
+									 Vector2i dstpoint,
                             const std::string& text,
                             Align align,
                             uint32_t caret) {
@@ -213,14 +213,13 @@
 	copytext = i18n::make_ligatures(copytext.c_str());
 	const LineCacheEntry& lce = d->get_line(style, copytext);
 
-	Vector2f dstpoint = dstpoint_i.cast<float>();
 	UI::correct_for_align(align, lce.width + 2 * LINE_MARGIN, &dstpoint);
 
 	if (lce.image)
-		dst.blit(Vector2f(dstpoint.x + LINE_MARGIN, dstpoint.y), lce.image.get());
+		dst.blit(Vector2i(dstpoint.x + LINE_MARGIN, dstpoint.y), lce.image.get());
 
 	if (caret <= copytext.size())
-		draw_caret(dst, style, dstpoint, copytext, caret);
+		draw_caret(dst, style, dstpoint.cast<float>(), copytext, caret);
 }
 
 /**
@@ -233,7 +232,7 @@
 	const LineCacheEntry& lce = d->get_line(style, text);
 
 	if (lce.image) {
-		dst.blit(dstpoint.cast<float>(), lce.image.get());
+		dst.blit(dstpoint, lce.image.get());
 	}
 
 	return lce.width;

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2017-02-28 20:07:07 +0000
+++ src/graphic/rendertarget.cc	2017-04-22 16:16:31 +0000
@@ -23,7 +23,6 @@
 #include "graphic/animation.h"
 #include "graphic/graphic.h"
 #include "graphic/surface.h"
-#include "graphic/text_layout.h"
 
 /**
  * Build a render target for the given surface.
@@ -119,21 +118,21 @@
 /**
  * Clip against window and pass those primitives along to the bitmap.
  */
-void RenderTarget::draw_rect(const Rectf& rect, const RGBColor& clr) {
-	Rectf r(rect);
+void RenderTarget::draw_rect(const Recti& rect, const RGBColor& clr) {
+	Rectf r(rect.cast<float>());
 	if (clip(r)) {
 		::draw_rect(r, clr, surface_);
 	}
 }
 
-void RenderTarget::fill_rect(const Rectf& rect, const RGBAColor& clr, BlendMode blend_mode) {
-	Rectf r(rect);
+void RenderTarget::fill_rect(const Recti& rect, const RGBAColor& clr, BlendMode blend_mode) {
+	Rectf r(rect.cast<float>());
 	if (clip(r))
 		surface_->fill_rect(r, clr, blend_mode);
 }
 
-void RenderTarget::brighten_rect(const Rectf& rect, int32_t factor) {
-	Rectf r(rect);
+void RenderTarget::brighten_rect(const Recti& rect, int32_t factor) {
+	Rectf r(rect.cast<float>());
 	if (clip(r))
 		surface_->brighten_rect(r, factor);
 }
@@ -143,15 +142,11 @@
  *
  * This blit function copies the pixels to the destination surface.
  */
-void RenderTarget::blit(const Vector2f& dst,
+void RenderTarget::blit(const Vector2i& dst,
                         const Image* image,
-                        BlendMode blend_mode,
-                        UI::Align align) {
-	Vector2f destination_point(dst);
-	UI::correct_for_align(align, image->width(), &destination_point);
-
+                        BlendMode blend_mode) {
 	Rectf source_rect(Vector2i(0, 0), image->width(), image->height());
-	Rectf destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
+	Rectf destination_rect(dst.x, dst.y, source_rect.w, source_rect.h);
 
 	if (to_surface_geometry(&destination_rect, &source_rect)) {
 		// I seem to remember seeing 1. a lot in blitting calls.
@@ -160,15 +155,11 @@
 	}
 }
 
-void RenderTarget::blit_monochrome(const Vector2f& dst,
+void RenderTarget::blit_monochrome(const Vector2i& dst,
                                    const Image* image,
-                                   const RGBAColor& blend_mode,
-                                   UI::Align align) {
-	Vector2f destination_point(dst);
-	UI::correct_for_align(align, image->width(), &destination_point);
-
+                                   const RGBAColor& blend_mode) {
 	Rectf source_rect(Vector2i(0, 0), image->width(), image->height());
-	Rectf destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
+	Rectf destination_rect(dst.x, dst.y, source_rect.w, source_rect.h);
 
 	if (to_surface_geometry(&destination_rect, &source_rect)) {
 		surface_->blit_monochrome(destination_rect, *image, source_rect, blend_mode);
@@ -178,7 +169,7 @@
 /**
  * Like \ref blit, but use only a sub-rectangle of the source image.
  */
-void RenderTarget::blitrect(const Vector2f& dst,
+void RenderTarget::blitrect(const Vector2i& dst,
                             const Image* image,
                             const Recti& gsrcrc,
                             BlendMode blend_mode) {

=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h	2017-02-23 19:38:51 +0000
+++ src/graphic/rendertarget.h	2017-04-22 16:16:31 +0000
@@ -58,22 +58,20 @@
 	int32_t height() const;
 
 	void draw_line_strip(const std::vector<Vector2f>& points, const RGBColor& color, float width);
-	void draw_rect(const Rectf&, const RGBColor&);
-	void fill_rect(const Rectf&, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
-	void brighten_rect(const Rectf&, int32_t factor);
+	void draw_rect(const Recti&, const RGBColor&);
+	void fill_rect(const Recti&, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
+	void brighten_rect(const Recti&, int32_t factor);
 
-	void blit(const Vector2f& dst,
+	void blit(const Vector2i& dst,
 	          const Image* image,
-	          BlendMode blend_mode = BlendMode::UseAlpha,
-	          UI::Align = UI::Align::kLeft);
+	          BlendMode blend_mode = BlendMode::UseAlpha);
 
 	// Like blit. See MonochromeBlitProgram for details.
-	void blit_monochrome(const Vector2f& dst,
+	void blit_monochrome(const Vector2i& dst,
 	                     const Image* image,
-	                     const RGBAColor& blend_mode,
-	                     UI::Align = UI::Align::kLeft);
+	                     const RGBAColor& blend_mode);
 
-	void blitrect(const Vector2f& dst,
+	void blitrect(const Vector2i& dst,
 	              const Image* image,
 	              const Recti& src,
 	              BlendMode blend_mode = BlendMode::UseAlpha);

=== modified file 'src/graphic/richtext.cc'
--- src/graphic/richtext.cc	2017-02-23 19:38:51 +0000
+++ src/graphic/richtext.cc	2017-04-22 16:16:31 +0000
@@ -61,7 +61,7 @@
 	}
 
 	void draw(RenderTarget& dst) override {
-		dst.blit(Vector2f(0, 0), image);
+		dst.blit(Vector2i(), image);
 	}
 
 	const Image* image;
@@ -498,7 +498,7 @@
 
 		if (dst.enter_window(bbox, &oldbox, &oldofs)) {
 			if (background)
-				dst.fill_rect(Rectf(0.f, 0.f, bbox.w, bbox.h), m->background_color);
+				dst.fill_rect(Recti(0, 0, bbox.w, bbox.h), m->background_color);
 			(*elt)->draw(dst);
 			dst.set_window(oldbox, oldofs);
 		}

=== modified file 'src/graphic/text_layout.cc'
--- src/graphic/text_layout.cc	2017-03-25 15:32:49 +0000
+++ src/graphic/text_layout.cc	2017-04-22 16:16:31 +0000
@@ -187,7 +187,7 @@
  * subsampled rendering - this can lead to blurry texts. That is why we
  * never do float divisions in this function.
  */
-void correct_for_align(Align align, uint32_t w, Vector2f* pt) {
+void correct_for_align(Align align, uint32_t w, Vector2i* pt) {
 
 	if (align == Align::kCenter)
 		pt->x -= w / 2;
@@ -198,7 +198,7 @@
 /**
  * Adjust the y coordinate in 'point 'pt' to vertically center an element with height 'h'.
  */
-void center_vertically(uint32_t h, Vector2f* pt) {
+void center_vertically(uint32_t h, Vector2i* pt) {
 	pt->y -= h / 2;
 }
 }  // namespace UI

=== modified file 'src/graphic/text_layout.h'
--- src/graphic/text_layout.h	2017-02-28 20:07:07 +0000
+++ src/graphic/text_layout.h	2017-04-22 16:16:31 +0000
@@ -103,8 +103,8 @@
 
 Align mirror_alignment(Align alignment);
 
-void center_vertically(uint32_t h, Vector2f* pt);
-void correct_for_align(Align, uint32_t w, Vector2f* pt);
+void center_vertically(uint32_t h, Vector2i* pt);
+void correct_for_align(Align, uint32_t w, Vector2i* pt);
 
 }  // namespace UI
 

=== modified file 'src/graphic/wordwrap.cc'
--- src/graphic/wordwrap.cc	2017-03-25 15:32:49 +0000
+++ src/graphic/wordwrap.cc	2017-04-22 16:16:31 +0000
@@ -336,7 +336,7 @@
 		if (where.y >= dst.height() || int32_t(where.y + fontheight) <= 0)
 			continue;
 
-		Vector2f point(where.x, where.y);
+		Vector2i point(where.x, where.y);
 
 		if (alignment == UI::Align::kRight) {
 			point.x += wrapwidth_ - kLineMargin;
@@ -353,9 +353,9 @@
 			int caret_x = text_width(line_to_caret, fontsize_);
 
 			const Image* caret_image = g_gr->images().get("images/ui_basic/caret.png");
-			Vector2f caretpt;
+			Vector2i caretpt;
 			caretpt.x = point.x + caret_x - caret_image->width() + kLineMargin;
-			caretpt.y = point.y + (fontheight - caret_image->height()) / 2.f;
+			caretpt.y = point.y + (fontheight - caret_image->height()) / 2;
 			dst.blit(caretpt, caret_image);
 		}
 	}

=== modified file 'src/logic/map_objects/map_object.cc'
--- src/logic/map_objects/map_object.cc	2017-02-23 19:38:51 +0000
+++ src/logic/map_objects/map_object.cc	2017-04-22 16:16:31 +0000
@@ -471,19 +471,19 @@
 	const Image* rendered_census_info =
 	   UI::g_fh1->render(as_condensed(census, UI::Align::kCenter, font_size), 120);
 
-	// Rounding guarantees that text aligns with pixels to avoid subsampling.
-	const Vector2f census_pos = round(field_on_dst - Vector2f(0, 48) * scale).cast<float>();
+	const Vector2i base_pos = field_on_dst.cast<int>() - Vector2i(0, 48) * scale;
+	Vector2i census_pos(base_pos);
+	UI::correct_for_align(UI::Align::kCenter, rendered_census_info->width(), &census_pos);
 	if (draw_text & TextToDraw::kCensus) {
-		dst->blit(census_pos, rendered_census_info, BlendMode::UseAlpha, UI::Align::kCenter);
+		dst->blit(census_pos, rendered_census_info, BlendMode::UseAlpha);
 	}
 
 	if (draw_text & TextToDraw::kStatistics && !statictics.empty()) {
-		const Vector2f statistics_pos =
-		   round(census_pos + Vector2f(0, rendered_census_info->height() / 2.f + 10 * scale))
-		      .cast<float>();
-		dst->blit(statistics_pos,
-		          UI::g_fh1->render(as_condensed(statictics, UI::Align::kCenter, font_size)),
-		          BlendMode::UseAlpha, UI::Align::kCenter);
+		Vector2i statistics_pos =
+		   base_pos + Vector2i(0, rendered_census_info->height() / 2 + 10 * scale);
+		const Image* rendered_statictics = UI::g_fh1->render(as_condensed(statictics, UI::Align::kCenter, font_size));
+		UI::correct_for_align(UI::Align::kCenter, rendered_statictics->width(), &statistics_pos);
+		dst->blit(statistics_pos, rendered_statictics, BlendMode::UseAlpha);
 	}
 }
 

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2017-01-31 07:18:19 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2017-04-22 16:16:31 +0000
@@ -451,8 +451,8 @@
 
 	const Vector2f point_on_dst = calc_drawpos(game, field_on_dst, scale);
 	draw_info_icon(
-	   point_on_dst -
-	      Vector2f(0.f, (g_gr->animations().get_animation(get_current_anim()).height() - 7) * scale),
+	   point_on_dst.cast<int>() -
+	      Vector2i(0, (g_gr->animations().get_animation(get_current_anim()).height() - 7) * scale),
 	   scale, true, dst);
 	draw_inner(game, point_on_dst, scale, dst);
 }
@@ -460,7 +460,7 @@
 /**
  * Draw the info icon (level indicators + health bar) for this soldier.
  */
-void Soldier::draw_info_icon(Vector2f draw_position,
+void Soldier::draw_info_icon(Vector2i draw_position,
                              float scale,
                              const bool anchor_below,
                              RenderTarget* dst) const {
@@ -492,29 +492,26 @@
 	assert(kSoldierHealthBarWidth > dimension);
 #endif
 
-	const float icon_size = healthpic->width();
-	const float half_width = kSoldierHealthBarWidth;
+	const int icon_size = healthpic->width();
 
 	if (!anchor_below) {
-		float totalwidth = 2 * half_width;
-		float totalheight = 5.f + 2 * icon_size;
-		draw_position.x += (totalwidth / 2.f) * scale;
-		draw_position.y += (totalheight - 5.f) * scale;
+		draw_position.x += kSoldierHealthBarWidth * scale;
+		draw_position.y += 2 * icon_size * scale;
 	} else {
-		draw_position.y -= 5.f * scale;
+		draw_position.y -= 5 * scale;
 	}
 
 	// Draw energy bar
 	assert(get_max_health());
-	const Rectf energy_outer(
-	   draw_position - Vector2f(half_width, 0.f) * scale, half_width * 2.f * scale, 5.f * scale);
+	const Recti energy_outer(
+	   draw_position - Vector2i(kSoldierHealthBarWidth, 0) * scale, kSoldierHealthBarWidth * 2 * scale, 5 * scale);
 	dst->fill_rect(energy_outer, RGBColor(255, 255, 255));
 
-	float health_width = 2.f * (half_width - 1.f) * current_health_ / get_max_health();
-	Rectf energy_inner(
-	   draw_position + Vector2f(-half_width + 1.f, 1.f) * scale, health_width * scale, 3 * scale);
-	Rectf energy_complement(energy_inner.origin() + Vector2f(health_width, 0.f) * scale,
-	                        (2 * (half_width - 1) - health_width) * scale, 3 * scale);
+	int health_width = 2 * (kSoldierHealthBarWidth - 1) * current_health_ / get_max_health();
+	Recti energy_inner(
+	   draw_position + Vector2i(-kSoldierHealthBarWidth + 1, 1) * scale, health_width * scale, 3 * scale);
+	Recti energy_complement(energy_inner.origin() + Vector2i(health_width, 0) * scale,
+	                        (2 * (kSoldierHealthBarWidth - 1) - health_width) * scale, 3 * scale);
 
 	const RGBColor& color = owner().get_playercolor();
 	RGBColor complement_color;
@@ -528,15 +525,15 @@
 	dst->fill_rect(energy_complement, complement_color);
 
 	const auto draw_level_image = [icon_size, scale, &draw_position, dst](
-	   const Vector2f& offset, const Image* image) {
+	   const Vector2i& offset, const Image* image) {
 		dst->blitrect_scale(
 		   Rectf(draw_position + offset * icon_size * scale, icon_size * scale, icon_size * scale),
 		   image, Recti(0, 0, icon_size, icon_size), 1.f, BlendMode::UseAlpha);
 	};
-	draw_level_image(Vector2f(-1.f, -2.f), attackpic);
-	draw_level_image(Vector2f(0.f, -2.f), defensepic);
-	draw_level_image(Vector2f(-1.f, -1.f), healthpic);
-	draw_level_image(Vector2f(0.f, -1.f), evadepic);
+	draw_level_image(Vector2i(-1, -2), attackpic);
+	draw_level_image(Vector2i(0, -2), defensepic);
+	draw_level_image(Vector2i(-1, -1), healthpic);
+	draw_level_image(Vector2i(0, -1), evadepic);
 }
 
 /**

=== modified file 'src/logic/map_objects/tribes/soldier.h'
--- src/logic/map_objects/tribes/soldier.h	2017-01-25 18:55:59 +0000
+++ src/logic/map_objects/tribes/soldier.h	2017-04-22 16:16:31 +0000
@@ -219,7 +219,7 @@
 	// Draw the info icon containing health bar and levels. If 'anchor_below' is
 	// true, the icon is drawn horizontally centered above Otherwise, the icon
 	// is drawn below and right of 'draw_position'.
-	void draw_info_icon(Vector2f draw_position,
+	void draw_info_icon(Vector2i draw_position,
 	                    const float scale,
 	                    const bool anchor_below,
 	                    RenderTarget*) const;

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2017-02-27 22:09:57 +0000
+++ src/ui_basic/button.cc	2017-04-22 16:16:31 +0000
@@ -161,25 +161,25 @@
 
 	// Draw the background
 	if (pic_background_) {
-		dst.fill_rect(Rectf(0.f, 0.f, get_w(), get_h()), RGBAColor(0, 0, 0, 255));
+		dst.fill_rect(Recti(0, 0, get_w(), get_h()), RGBAColor(0, 0, 0, 255));
 		dst.tile(
 		   Recti(Vector2i(0, 0), get_w(), get_h()), pic_background_, Vector2i(get_x(), get_y()));
 	}
 
 	if (is_flat && highlighted_)
-		dst.brighten_rect(Rectf(0.f, 0.f, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, 0, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
 
 	//  If we've got a picture, draw it centered
 	if (pic_custom_) {
 		if (image_mode_ == UI::Button::ImageMode::kUnscaled) {
 			if (!is_monochrome) {
-				dst.blit(Vector2f((get_w() - static_cast<int32_t>(pic_custom_->width())) / 2.f,
-				                  (get_h() - static_cast<int32_t>(pic_custom_->height())) / 2.f),
+				dst.blit(Vector2i((get_w() - static_cast<int32_t>(pic_custom_->width())) / 2,
+				                  (get_h() - static_cast<int32_t>(pic_custom_->height())) / 2),
 				         pic_custom_);
 			} else {
 				dst.blit_monochrome(
-				   Vector2f((get_w() - static_cast<int32_t>(pic_custom_->width())) / 2.f,
-				            (get_h() - static_cast<int32_t>(pic_custom_->height())) / 2.f),
+				   Vector2i((get_w() - static_cast<int32_t>(pic_custom_->width())) / 2,
+				            (get_h() - static_cast<int32_t>(pic_custom_->height())) / 2),
 				   pic_custom_, RGBAColor(255, 255, 255, 127));
 			}
 		} else {
@@ -213,7 +213,7 @@
 		                   is_monochrome ? UI_FONT_CLR_DISABLED : UI_FONT_CLR_FG);
 		// Blit on pixel boundary (not float), so that the text is blitted pixel perfect.
 		dst.blit(
-		   Vector2f((get_w() - entry_text_im->width()) / 2, (get_h() - entry_text_im->height()) / 2),
+		   Vector2i((get_w() - entry_text_im->width()) / 2, (get_h() - entry_text_im->height()) / 2),
 		   entry_text_im);
 	}
 
@@ -229,36 +229,36 @@
 		//  Button is a normal one, not flat. We invert the behaviour for kPermpressed.
 		if (is_permpressed == (pressed_ && highlighted_)) {
 			//  top edge
-			dst.brighten_rect(Rectf(0.f, 0.f, get_w(), 2.f), BUTTON_EDGE_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(0, 0, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
 			//  left edge
-			dst.brighten_rect(Rectf(0, 2, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(0, 2, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 			//  bottom edge
-			dst.fill_rect(Rectf(2, get_h() - 2, get_w() - 2, 1), black);
-			dst.fill_rect(Rectf(1, get_h() - 1, get_w() - 1, 1), black);
+			dst.fill_rect(Recti(2, get_h() - 2, get_w() - 2, 1), black);
+			dst.fill_rect(Recti(1, get_h() - 1, get_w() - 1, 1), black);
 			//  right edge
-			dst.fill_rect(Rectf(get_w() - 2, 2, 1, get_h() - 2), black);
-			dst.fill_rect(Rectf(get_w() - 1, 1, 1, get_h() - 1), black);
+			dst.fill_rect(Recti(get_w() - 2, 2, 1, get_h() - 2), black);
+			dst.fill_rect(Recti(get_w() - 1, 1, 1, get_h() - 1), black);
 		} else {
 			//  bottom edge
-			dst.brighten_rect(Rectf(0, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(0, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
 			//  right edge
-			dst.brighten_rect(Rectf(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 			//  top edge
-			dst.fill_rect(Rectf(0, 0, get_w() - 1, 1), black);
-			dst.fill_rect(Rectf(0, 1, get_w() - 2, 1), black);
+			dst.fill_rect(Recti(0, 0, get_w() - 1, 1), black);
+			dst.fill_rect(Recti(0, 1, get_w() - 2, 1), black);
 			//  left edge
-			dst.fill_rect(Rectf(0, 0, 1, get_h() - 1), black);
-			dst.fill_rect(Rectf(1, 0, 1, get_h() - 2), black);
+			dst.fill_rect(Recti(0, 0, 1, get_h() - 1), black);
+			dst.fill_rect(Recti(1, 0, 1, get_h() - 2), black);
 		}
 	} else {
 		//  Button is flat, do not draw borders, instead, if it is pressed, draw
 		//  a box around it.
 		if (enabled_ && highlighted_) {
 			RGBAColor shade(100, 100, 100, 80);
-			dst.fill_rect(Rectf(0, 0, get_w(), 2), shade);
-			dst.fill_rect(Rectf(0, 2, 2, get_h() - 2), shade);
-			dst.fill_rect(Rectf(0, get_h() - 2, get_w(), get_h()), shade);
-			dst.fill_rect(Rectf(get_w() - 2, 0, get_w(), get_h()), shade);
+			dst.fill_rect(Recti(0, 0, get_w(), 2), shade);
+			dst.fill_rect(Recti(0, 2, 2, get_h() - 2), shade);
+			dst.fill_rect(Recti(0, get_h() - 2, get_w(), get_h()), shade);
+			dst.fill_rect(Recti(get_w() - 2, 0, get_w(), get_h()), shade);
 		}
 	}
 }

=== modified file 'src/ui_basic/checkbox.cc'
--- src/ui_basic/checkbox.cc	2017-02-23 17:58:25 +0000
+++ src/ui_basic/checkbox.cc	2017-04-22 16:16:31 +0000
@@ -134,18 +134,18 @@
 		const uint16_t w = pic_graphics_->width();
 		const uint16_t h = pic_graphics_->height();
 
-		dst.blit(Vector2f((get_inner_w() - w) / 2, (get_inner_h() - h) / 2), pic_graphics_);
+		dst.blit(Vector2i((get_inner_w() - w) / 2, (get_inner_h() - h) / 2), pic_graphics_);
 
 		if (flags_ & Is_Checked) {
-			dst.draw_rect(Rectf(0.f, 0.f, get_w(), get_h()), RGBColor(229, 116, 2));
+			dst.draw_rect(Recti(0, 0, get_w(), get_h()), RGBColor(229, 116, 2));
 		} else if (flags_ & Is_Highlighted) {
-			dst.draw_rect(Rectf(0.f, 0.f, get_w(), get_h()), RGBColor(100, 100, 80));
+			dst.draw_rect(Recti(0, 0, get_w(), get_h()), RGBColor(100, 100, 80));
 		}
 	} else {
 		static_assert(0 <= kStateboxSize, "assert(0 <= STATEBOX_WIDTH) failed.");
 		static_assert(0 <= kStateboxSize, "assert(0 <= STATEBOX_HEIGHT) failed.");
-		Vector2f image_anchor(0.f, 0.f);
-		Vector2f text_anchor(kStateboxSize + kPadding, 0);
+		Vector2i image_anchor(0, 0);
+		Vector2i text_anchor(kStateboxSize + kPadding, 0);
 
 		if (rendered_text_) {
 			if (UI::g_fh1->fontset()->is_rtl()) {
@@ -153,7 +153,7 @@
 				image_anchor.x = rendered_text_->width() + kPadding;
 				image_anchor.y = (get_h() - kStateboxSize) / 2;
 			}
-			dst.blit(text_anchor, rendered_text_, BlendMode::UseAlpha, UI::Align::kLeft);
+			dst.blit(text_anchor, rendered_text_, BlendMode::UseAlpha);
 		}
 
 		dst.blitrect(
@@ -162,7 +162,7 @@
 
 		if (flags_ & Is_Highlighted)
 			dst.draw_rect(
-			   Rectf(image_anchor, kStateboxSize + 1, kStateboxSize + 1), RGBColor(100, 100, 80));
+			   Recti(image_anchor, kStateboxSize + 1, kStateboxSize + 1), RGBColor(100, 100, 80));
 	}
 }
 

=== modified file 'src/ui_basic/editbox.cc'
--- src/ui_basic/editbox.cc	2017-02-28 20:07:07 +0000
+++ src/ui_basic/editbox.cc	2017-04-22 16:16:31 +0000
@@ -363,19 +363,19 @@
 		static const RGBColor black(0, 0, 0);
 
 		// bottom edge
-		dst.brighten_rect(Rectf(0, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// right edge
-		dst.brighten_rect(Rectf(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// top edge
-		dst.fill_rect(Rectf(0.f, 0.f, get_w() - 1, 1), black);
-		dst.fill_rect(Rectf(0.f, 1.f, get_w() - 2, 1), black);
+		dst.fill_rect(Recti(0, 0, get_w() - 1, 1), black);
+		dst.fill_rect(Recti(0, 1, get_w() - 2, 1), black);
 		// left edge
-		dst.fill_rect(Rectf(0.f, 0.f, 1, get_h() - 1), black);
-		dst.fill_rect(Rectf(1.f, 0.f, 1, get_h() - 2), black);
+		dst.fill_rect(Recti(0, 0, 1, get_h() - 1), black);
+		dst.fill_rect(Recti(1, 0, 1, get_h() - 2), black);
 	}
 
 	if (has_focus()) {
-		dst.brighten_rect(Rectf(0.f, 0.f, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, 0, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
 	}
 
 	const int max_width = get_w() - 2 * kMarginX;
@@ -390,7 +390,7 @@
 	         ->height() :
 	      entry_text_im->height();
 
-	Vector2f point(kMarginX, get_h() / 2);
+	Vector2i point(kMarginX, get_h() / 2);
 	if (m_->align == UI::Align::kRight) {
 		point.x += max_width - linewidth;
 	}
@@ -428,9 +428,9 @@
 		const uint16_t fontheight = text_height(m_->text, m_->fontsize);
 
 		const Image* caret_image = g_gr->images().get("images/ui_basic/caret.png");
-		Vector2f caretpt;
+		Vector2i caretpt;
 		caretpt.x = point.x + m_->scrolloffset + caret_x - caret_image->width() + kLineMargin;
-		caretpt.y = point.y + (fontheight - caret_image->height()) / 2.f;
+		caretpt.y = point.y + (fontheight - caret_image->height()) / 2;
 		dst.blit(caretpt, caret_image);
 	}
 }

=== modified file 'src/ui_basic/fullscreen_window.cc'
--- src/ui_basic/fullscreen_window.cc	2017-02-23 19:38:51 +0000
+++ src/ui_basic/fullscreen_window.cc	2017-04-22 16:16:31 +0000
@@ -150,7 +150,7 @@
 			const int h = (tiling == kHorizontal) ? image->height() : get_h();
 			dst.tile(Recti(x, y, w, h), image, Vector2i(0, 0));
 		} else {
-			dst.blit(Vector2f(x, y), image);
+			dst.blit(Vector2i(x, y), image);
 		}
 	}
 }

=== modified file 'src/ui_basic/icon.cc'
--- src/ui_basic/icon.cc	2017-01-25 18:55:59 +0000
+++ src/ui_basic/icon.cc	2017-04-22 16:16:31 +0000
@@ -63,7 +63,7 @@
 		                   Recti(0, 0, pic_->width(), pic_->height()), 1., BlendMode::UseAlpha);
 	}
 	if (draw_frame_) {
-		dst.draw_rect(Rectf(0.f, 0.f, get_w(), get_h()), framecolor_);
+		dst.draw_rect(Recti(0, 0, get_w(), get_h()), framecolor_);
 	}
 }
 }

=== modified file 'src/ui_basic/listselect.cc'
--- src/ui_basic/listselect.cc	2017-03-06 06:57:47 +0000
+++ src/ui_basic/listselect.cc	2017-04-22 16:16:31 +0000
@@ -362,17 +362,17 @@
 	if (selection_mode_ == ListselectLayout::kDropdown) {
 		RGBAColor black(0, 0, 0, 255);
 		//  top edge
-		dst.brighten_rect(Rectf(0.f, 0.f, get_w(), 2.f), BUTTON_EDGE_BRIGHT_FACTOR / 4);
+		dst.brighten_rect(Recti(0, 0, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR / 4);
 		//  left edge
-		dst.brighten_rect(Rectf(0.f, 0.f, 2.f, get_h()), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, 0, 2, get_h()), BUTTON_EDGE_BRIGHT_FACTOR);
 		//  bottom edge
-		dst.fill_rect(Rectf(2.f, get_h() - 2.f, get_eff_w() - 2.f, 1.f), black);
-		dst.fill_rect(Rectf(1.f, get_h() - 1.f, get_eff_w() - 1.f, 1.f), black);
+		dst.fill_rect(Recti(2, get_h() - 2, get_eff_w() - 2, 1), black);
+		dst.fill_rect(Recti(1, get_h() - 1, get_eff_w() - 1, 1), black);
 		//  right edge
-		dst.fill_rect(Rectf(get_w() - 2.f, 1.f, 1.f, get_h() - 1.f), black);
-		dst.fill_rect(Rectf(get_w() - 1.f, 0.f, 1.f, get_h()), black);
+		dst.fill_rect(Recti(get_w() - 2, 1, 1, get_h() - 1), black);
+		dst.fill_rect(Recti(get_w() - 1, 0, 1, get_h()), black);
 	} else {
-		dst.brighten_rect(Rectf(0.f, 0.f, get_eff_w(), get_h()), ms_darken_value);
+		dst.brighten_rect(Recti(0, 0, get_eff_w(), get_h()), ms_darken_value);
 	}
 
 	while (idx < entry_records_.size()) {
@@ -390,14 +390,14 @@
 			break;
 		}
 
-		Vector2f point(selection_mode_ == ListselectLayout::kDropdown ? 3.f : 1.f, y);
+		Vector2i point(selection_mode_ == ListselectLayout::kDropdown ? 3 : 1, y);
 		uint32_t maxw =
 		   get_eff_w() -
 		   (selection_mode_ == ListselectLayout::kDropdown ? scrollbar_.is_enabled() ? 4 : 5 : 2);
 
 		// Highlight the current selected entry
 		if (idx == selection_) {
-			Rectf r(point, maxw, lineheight_);
+			Recti r(point, maxw, lineheight_);
 			if (r.x < 0) {
 				r.w += r.x;
 				r.x = 0;
@@ -417,7 +417,7 @@
 
 		// Now draw pictures
 		if (er.pic) {
-			dst.blit(Vector2f(UI::g_fh1->fontset()->is_rtl() ? get_eff_w() - er.pic->width() - 1 : 1,
+			dst.blit(Vector2i(UI::g_fh1->fontset()->is_rtl() ? get_eff_w() - er.pic->width() - 1 : 1,
 			                  y + (get_lineheight() - er.pic->height()) / 2),
 			         er.pic);
 		}

=== modified file 'src/ui_basic/multilineeditbox.cc'
--- src/ui_basic/multilineeditbox.cc	2017-03-04 18:02:23 +0000
+++ src/ui_basic/multilineeditbox.cc	2017-04-22 16:16:31 +0000
@@ -433,19 +433,19 @@
 		static const RGBColor black(0, 0, 0);
 
 		// bottom edge
-		dst.brighten_rect(Rectf(0.f, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, get_h() - 2, get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// right edge
-		dst.brighten_rect(Rectf(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(get_w() - 2, 0, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// top edge
-		dst.fill_rect(Rectf(0, 0, get_w() - 1, 1), black);
-		dst.fill_rect(Rectf(0, 1, get_w() - 2, 1), black);
+		dst.fill_rect(Recti(0, 0, get_w() - 1, 1), black);
+		dst.fill_rect(Recti(0, 1, get_w() - 2, 1), black);
 		// left edge
-		dst.fill_rect(Rectf(0, 0, 1, get_h() - 1), black);
-		dst.fill_rect(Rectf(1, 0, 1, get_h() - 2), black);
+		dst.fill_rect(Recti(0, 0, 1, get_h() - 1), black);
+		dst.fill_rect(Recti(1, 0, 1, get_h() - 2), black);
 	}
 
 	if (has_focus())
-		dst.brighten_rect(Rectf(0, 0, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, 0, get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
 
 	d_->refresh_ww();
 

=== modified file 'src/ui_basic/multilinetextarea.cc'
--- src/ui_basic/multilinetextarea.cc	2017-03-04 18:02:23 +0000
+++ src/ui_basic/multilinetextarea.cc	2017-04-22 16:16:31 +0000
@@ -174,7 +174,7 @@
 				anchor = RICHTEXT_MARGIN;
 			}
 
-			dst.blitrect(Vector2f(anchor, 0), text_im,
+			dst.blitrect(Vector2i(anchor, 0), text_im,
 			             Recti(0, scrollbar_.get_scrollpos(), blit_width, blit_height),
 			             BlendMode::UseAlpha);
 		}

=== modified file 'src/ui_basic/panel.cc'
--- src/ui_basic/panel.cc	2017-02-27 13:53:04 +0000
+++ src/ui_basic/panel.cc	2017-04-22 16:16:31 +0000
@@ -191,7 +191,7 @@
 			RenderTarget& rt = *g_gr->get_render_target();
 			forefather->do_draw(rt);
 			rt.blit(
-			   (app->get_mouse_position() - Vector2i(3, 7)).cast<float>(),
+			   (app->get_mouse_position() - Vector2i(3, 7)),
 			   WLApplication::get()->is_mouse_pressed() ? default_cursor_click_ : default_cursor_);
 			forefather->do_tooltip();
 			g_gr->refresh();
@@ -1068,9 +1068,9 @@
 	uint16_t tip_width = rendered_text->width() + 4;
 	uint16_t tip_height = rendered_text->height() + 4;
 
-	Rectf r(WLApplication::get()->get_mouse_position() + Vector2i(2, 32), tip_width, tip_height);
-	const Vector2f tooltip_bottom_right = r.opposite_of_origin();
-	const Vector2f screen_bottom_right(g_gr->get_xres(), g_gr->get_yres());
+	Recti r(WLApplication::get()->get_mouse_position() + Vector2i(2, 32), tip_width, tip_height);
+	const Vector2i tooltip_bottom_right = r.opposite_of_origin();
+	const Vector2i screen_bottom_right(g_gr->get_xres(), g_gr->get_yres());
 	if (screen_bottom_right.x < tooltip_bottom_right.x)
 		r.x -= 4 + r.w;
 	if (screen_bottom_right.y < tooltip_bottom_right.y)
@@ -1078,7 +1078,7 @@
 
 	dst.fill_rect(r, RGBColor(63, 52, 34));
 	dst.draw_rect(r, RGBColor(0, 0, 0));
-	dst.blit(r.origin() + Vector2f(2.f, 2.f), rendered_text);
+	dst.blit(r.origin() + Vector2i(2, 2), rendered_text);
 	return true;
 }
 }

=== modified file 'src/ui_basic/progressbar.cc'
--- src/ui_basic/progressbar.cc	2017-02-26 11:00:07 +0000
+++ src/ui_basic/progressbar.cc	2017-04-22 16:16:31 +0000
@@ -75,13 +75,13 @@
 		const float w = get_w() * fraction;
 		assert(w <= get_w());
 
-		dst.fill_rect(Rectf(0.f, 0.f, w, get_h()), color);
-		dst.fill_rect(Rectf(w, 0.f, get_w() - w, get_h()), RGBColor(0, 0, 0));
+		dst.fill_rect(Recti(0, 0, w, get_h()), color);
+		dst.fill_rect(Recti(w, 0, get_w() - w, get_h()), RGBColor(0, 0, 0));
 	} else {
 		const uint32_t h = static_cast<uint32_t>(get_h() * (1.0f - fraction));
 
-		dst.fill_rect(Rectf(0.f, 0.f, get_w(), h), RGBColor(0, 0, 0));
-		dst.fill_rect(Rectf(0.f, h, get_w(), get_h() - h), color);
+		dst.fill_rect(Recti(0, 0, get_w(), h), RGBColor(0, 0, 0));
+		dst.fill_rect(Recti(0, h, get_w(), get_h() - h), color);
 	}
 
 	// Print the state in percent without decimal points.
@@ -89,8 +89,9 @@
 	                                   UI_FONT_CLR_BRIGHT.hex_value() % floor(fraction * 100.f))
 	                                     .str();
 	const Image* rendered_text = UI::g_fh1->render(as_uifont(progress_text));
-	Vector2f pos(get_w() / 2, get_h() / 2);
+	Vector2i pos(get_w() / 2, get_h() / 2);
+	UI::correct_for_align(UI::Align::kCenter, rendered_text->width(), &pos);
 	UI::center_vertically(rendered_text->height(), &pos);
-	dst.blit(pos, rendered_text, BlendMode::UseAlpha, UI::Align::kCenter);
+	dst.blit(pos, rendered_text, BlendMode::UseAlpha);
 }
 }

=== modified file 'src/ui_basic/progresswindow.cc'
--- src/ui_basic/progresswindow.cc	2017-02-24 10:21:37 +0000
+++ src/ui_basic/progresswindow.cc	2017-04-22 16:16:31 +0000
@@ -70,7 +70,7 @@
 	label_rectangle_.y = label_center_.y - h / 2 - PROGRESS_STATUS_RECT_PADDING;
 	label_rectangle_.h = h + 2 * PROGRESS_STATUS_RECT_PADDING;
 
-	Rectf border_rect = label_rectangle_;
+	Recti border_rect = label_rectangle_;
 	border_rect.x -= PROGRESS_STATUS_BORDER_X;
 	border_rect.y -= PROGRESS_STATUS_BORDER_Y;
 	border_rect.w += 2 * PROGRESS_STATUS_BORDER_X;
@@ -100,8 +100,9 @@
 	rt.fill_rect(label_rectangle_, PROGRESS_FONT_COLOR_BG);
 	const Image* rendered_text =
 	   UI::g_fh1->render(as_uifont(description, UI_FONT_SIZE_SMALL, PROGRESS_FONT_COLOR_FG));
+	UI::correct_for_align(UI::Align::kCenter, rendered_text->width(), &label_center_);
 	UI::center_vertically(rendered_text->height(), &label_center_);
-	rt.blit(label_center_, rendered_text, BlendMode::UseAlpha, UI::Align::kCenter);
+	rt.blit(label_center_, rendered_text, BlendMode::UseAlpha);
 
 #ifdef _WIN32
 	// Pump events to prevent "not responding" on windows

=== modified file 'src/ui_basic/progresswindow.h'
--- src/ui_basic/progresswindow.h	2017-02-24 10:21:37 +0000
+++ src/ui_basic/progresswindow.h	2017-04-22 16:16:31 +0000
@@ -63,8 +63,8 @@
 private:
 	using VisualizationArray = std::vector<IProgressVisualization*>;
 
-	Vector2f label_center_;
-	Rectf label_rectangle_;
+	Vector2i label_center_;
+	Recti label_rectangle_;
 	VisualizationArray visualizations_;
 	std::string background_;
 

=== modified file 'src/ui_basic/scrollbar.cc'
--- src/ui_basic/scrollbar.cc	2017-02-27 13:48:29 +0000
+++ src/ui_basic/scrollbar.cc	2017-04-22 16:16:31 +0000
@@ -233,7 +233,7 @@
 	set_scrollpos(pos);
 }
 
-void Scrollbar::draw_button(RenderTarget& dst, Area area, const Rectf& r) {
+void Scrollbar::draw_button(RenderTarget& dst, Area area, const Recti& r) {
 	dst.tile(r.cast<int>(), pic_buttons_, Vector2i(get_x(), get_y()));
 
 	// Draw the picture
@@ -250,7 +250,7 @@
 		int blit_height = image_scale * pic->height();
 
 		dst.blitrect_scale(
-		   Rectf(r.origin() + Vector2f((r.w - blit_width) / 2.f, (r.h - blit_height) / 2.f),
+		   Rectf(r.origin() + Vector2i((r.w - blit_width) / 2, (r.h - blit_height) / 2),
 		         blit_width, blit_height),
 		   pic, Recti(0, 0, pic->width(), pic->height()), 1., BlendMode::UseAlpha);
 	}
@@ -260,46 +260,46 @@
 
 	if (area != pressed_) {
 		// top edge
-		dst.brighten_rect(Rectf(r.origin(), r.w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.origin(), r.w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// left edge
-		dst.brighten_rect(Rectf(r.origin() + Vector2f(0, 2), 2, r.h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.origin() + Vector2i(0, 2), 2, r.h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// bottom edge
-		dst.fill_rect(Rectf(r.origin() + Vector2f(2, r.h - 2), r.w - 2, 1), black);
-		dst.fill_rect(Rectf(r.origin() + Vector2f(1, r.h - 1), r.w - 1, 1), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(2, r.h - 2), r.w - 2, 1), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(1, r.h - 1), r.w - 1, 1), black);
 		// right edge
-		dst.fill_rect(Rectf(r.origin() + Vector2f(r.w - 2, 2), 1, r.h - 2), black);
-		dst.fill_rect(Rectf(r.origin() + Vector2f(r.w - 1, 1), 1, r.h - 1), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(r.w - 2, 2), 1, r.h - 2), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(r.w - 1, 1), 1, r.h - 1), black);
 	} else {
 		// bottom edge
 		dst.brighten_rect(
-		   Rectf(r.origin() + Vector2f(0, r.h - 2), r.w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   Recti(r.origin() + Vector2i(0, r.h - 2), r.w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// right edge
 		dst.brighten_rect(
-		   Rectf(r.origin() + Vector2f(r.w - 2, 0), 2, r.h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   Recti(r.origin() + Vector2i(r.w - 2, 0), 2, r.h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		// top edge
-		dst.fill_rect(Rectf(r.origin(), r.w - 1, 1), black);
-		dst.fill_rect(Rectf(r.origin() + Vector2f(0, 1), r.w - 2, 1), black);
+		dst.fill_rect(Recti(r.origin(), r.w - 1, 1), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(0, 1), r.w - 2, 1), black);
 		// left edge
-		dst.fill_rect(Rectf(r.origin(), 1, r.h - 1), black);
-		dst.fill_rect(Rectf(r.origin() + Vector2f(1, 0), 1, r.h - 2), black);
+		dst.fill_rect(Recti(r.origin(), 1, r.h - 1), black);
+		dst.fill_rect(Recti(r.origin() + Vector2i(1, 0), 1, r.h - 2), black);
 	}
 }
 
-void Scrollbar::draw_area(RenderTarget& dst, Area area, const Rectf& r) {
+void Scrollbar::draw_area(RenderTarget& dst, Area area, const Recti& r) {
 	//  background
 	dst.brighten_rect(r, area == pressed_ ? 2 * MOUSE_OVER_BRIGHT_FACTOR : MOUSE_OVER_BRIGHT_FACTOR);
 	if (horizontal_) {
 		//  top edge
-		dst.brighten_rect(Rectf(r.x, r.y, r.w - 1.f, 1.f), -BUTTON_EDGE_BRIGHT_FACTOR);
-		dst.brighten_rect(Rectf(r.x, r.y + 1.f, r.w - 2.f, 1.f), -BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.x, r.y, r.w - 1, 1), -BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.x, r.y + 1, r.w - 2, 1), -BUTTON_EDGE_BRIGHT_FACTOR);
 		//  bottom edge
-		dst.brighten_rect(Rectf(r.x, r.h - 2.f, r.w, 2.f), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.x, r.h - 2, r.w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 	} else {
 		//  right edge
-		dst.brighten_rect(Rectf(r.w - 2.f, r.y, 2.f, r.h), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.w - 2, r.y, 2, r.h), BUTTON_EDGE_BRIGHT_FACTOR);
 		//  left edge
-		dst.brighten_rect(Rectf(r.x, r.y, 1.f, r.h - 1.f), -BUTTON_EDGE_BRIGHT_FACTOR);
-		dst.brighten_rect(Rectf(r.x + 1.f, r.y, 1.f, r.h - 2.f), -BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.x, r.y, 1, r.h - 1), -BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(r.x + 1, r.y, 1, r.h - 2), -BUTTON_EDGE_BRIGHT_FACTOR);
 	}
 }
 
@@ -317,46 +317,46 @@
 		if ((2 * buttonsize_ + knobsize) > static_cast<uint32_t>(get_w())) {
 			// Our owner allocated too little space
 			if (static_cast<uint32_t>(get_w()) >= 2 * buttonsize_) {
-				draw_button(dst, Minus, Rectf(0, 0, get_w() / 2, get_h()));
-				draw_button(dst, Plus, Rectf(get_w() - buttonsize_, 0, get_w() / 2, get_h()));
+				draw_button(dst, Minus, Recti(0, 0, get_w() / 2, get_h()));
+				draw_button(dst, Plus, Recti(get_w() - buttonsize_, 0, get_w() / 2, get_h()));
 			} else {
-				draw_button(dst, Minus, Rectf(0.f, 0.f, get_w(), get_h()));
+				draw_button(dst, Minus, Recti(0, 0, get_w(), get_h()));
 			}
 			return;
 		}
 
-		draw_button(dst, Minus, Rectf(0, 0, buttonsize_, get_h()));
-		draw_button(dst, Plus, Rectf(get_w() - buttonsize_, 0, buttonsize_, get_h()));
-		draw_button(dst, Knob, Rectf(knobpos - knobsize / 2.f, 0, knobsize, get_h()));
+		draw_button(dst, Minus, Recti(0, 0, buttonsize_, get_h()));
+		draw_button(dst, Plus, Recti(get_w() - buttonsize_, 0, buttonsize_, get_h()));
+		draw_button(dst, Knob, Recti(knobpos - knobsize / 2, 0, knobsize, get_h()));
 
 		assert(buttonsize_ + knobsize / 2 <= knobpos);
 		draw_area(
-		   dst, MinusPage, Rectf(buttonsize_, 0, knobpos - buttonsize_ - knobsize / 2, get_h()));
+		   dst, MinusPage, Recti(buttonsize_, 0, knobpos - buttonsize_ - knobsize / 2, get_h()));
 		assert(knobpos + knobsize / 2 + buttonsize_ <= static_cast<uint32_t>(get_w()));
-		draw_area(dst, PlusPage, Rectf(knobpos + knobsize / 2.f, 0.f,
+		draw_area(dst, PlusPage, Recti(knobpos + knobsize / 2, 0,
 		                               get_w() - knobpos - knobsize / 2 - buttonsize_, get_h()));
 	} else {
 		if ((2 * buttonsize_ + knobsize) > static_cast<uint32_t>(get_h())) {
 			// Our owner allocated too little space
 			if (static_cast<uint32_t>(get_h()) >= 2 * buttonsize_) {
-				draw_button(dst, Minus, Rectf(0.f, 0.f, get_w(), get_h() / 2.f));
-				draw_button(dst, Plus, Rectf(0.f, get_h() - buttonsize_, get_w(), get_h() / 2));
+				draw_button(dst, Minus, Recti(0, 0, get_w(), get_h() / 2));
+				draw_button(dst, Plus, Recti(0, get_h() - buttonsize_, get_w(), get_h() / 2));
 			} else {
-				draw_button(dst, Minus, Rectf(0.f, 0.f, get_w(), get_h()));
+				draw_button(dst, Minus, Recti(0, 0, get_w(), get_h()));
 			}
 			return;
 		}
 
-		draw_button(dst, Minus, Rectf(0, 0, get_w(), buttonsize_));
-		draw_button(dst, Plus, Rectf(0, get_h() - buttonsize_, get_w(), buttonsize_));
-		draw_button(dst, Knob, Rectf(0, knobpos - knobsize / 2.f, get_w(), knobsize));
+		draw_button(dst, Minus, Recti(0, 0, get_w(), buttonsize_));
+		draw_button(dst, Plus, Recti(0, get_h() - buttonsize_, get_w(), buttonsize_));
+		draw_button(dst, Knob, Recti(0, knobpos - knobsize / 2, get_w(), knobsize));
 
 		assert(buttonsize_ + knobsize / 2 <= knobpos);
 		draw_area(
-		   dst, MinusPage, Rectf(0.f, buttonsize_, get_w(), knobpos - buttonsize_ - knobsize / 2));
+		   dst, MinusPage, Recti(0, buttonsize_, get_w(), knobpos - buttonsize_ - knobsize / 2));
 		assert(knobpos + knobsize / 2 + buttonsize_ <= static_cast<uint32_t>(get_h()));
-		draw_area(dst, PlusPage, Rectf(0.f, knobpos + knobsize / 2.f, get_w(),
-		                               get_h() - knobpos - knobsize / 2.f - buttonsize_));
+		draw_area(dst, PlusPage, Recti(0, knobpos + knobsize / 2, get_w(),
+		                               get_h() - knobpos - knobsize / 2 - buttonsize_));
 	}
 }
 

=== modified file 'src/ui_basic/scrollbar.h'
--- src/ui_basic/scrollbar.h	2017-01-25 18:55:59 +0000
+++ src/ui_basic/scrollbar.h	2017-04-22 16:16:31 +0000
@@ -82,8 +82,8 @@
 
 	void action(Area area);
 
-	void draw_button(RenderTarget&, Area, const Rectf&);
-	void draw_area(RenderTarget& dst, Area area, const Rectf& r);
+	void draw_button(RenderTarget&, Area, const Recti&);
+	void draw_area(RenderTarget& dst, Area area, const Recti& r);
 	void draw(RenderTarget&) override;
 	void think() override;
 

=== modified file 'src/ui_basic/slider.cc'
--- src/ui_basic/slider.cc	2017-02-24 19:22:36 +0000
+++ src/ui_basic/slider.cc	2017-04-22 16:16:31 +0000
@@ -152,34 +152,34 @@
 	   (Recti(Vector2i(x, y), w, h), pic_background_, Vector2i(get_x(), get_y()));
 
 	if (highlighted_)
-		dst.brighten_rect(Rectf(x, y, w, h), MOUSE_OVER_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(x, y, w, h), MOUSE_OVER_BRIGHT_FACTOR);
 
 	if (pressed_) {       //  draw border
 		dst.brighten_rect  //  bottom edge
-		   (Rectf(x, y + h - 2, w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(x, y + h - 2, w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		dst.brighten_rect  //  right edge
-		   (Rectf(x + w - 2, y, 2, h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(x + w - 2, y, 2, h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 
 		//  top edge
-		dst.fill_rect(Rectf(x, y, w - 1, 1), black);
-		dst.fill_rect(Rectf(x, y + 1, w - 2, 1), black);
+		dst.fill_rect(Recti(x, y, w - 1, 1), black);
+		dst.fill_rect(Recti(x, y + 1, w - 2, 1), black);
 
 		//  left edge
-		dst.fill_rect(Rectf(x, y, 1, h - 1), black);
-		dst.fill_rect(Rectf(x + 1, y, 1, h - 2), black);
+		dst.fill_rect(Recti(x, y, 1, h - 1), black);
+		dst.fill_rect(Recti(x + 1, y, 1, h - 2), black);
 	} else {
 		dst.brighten_rect  //  top edge
-		   (Rectf(x, y, w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(x, y, w, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		dst.brighten_rect  //  left edge
-		   (Rectf(x, y + 2, 2, h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(x, y + 2, 2, h - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 
 		//  bottom edge
-		dst.fill_rect(Rectf(x + 2, y + h - 2, w - 2, 1), black);
-		dst.fill_rect(Rectf(x + 1, y + h - 1, w - 1, 1), black);
+		dst.fill_rect(Recti(x + 2, y + h - 2, w - 2, 1), black);
+		dst.fill_rect(Recti(x + 1, y + h - 1, w - 1, 1), black);
 
 		//  right edge
-		dst.fill_rect(Rectf(x + w - 2, y + 2, 1, h - 2), black);
-		dst.fill_rect(Rectf(x + w - 1, y + 1, 1, h - 1), black);
+		dst.fill_rect(Recti(x + w - 2, y + 2, 1, h - 2), black);
+		dst.fill_rect(Recti(x + w - 1, y + 1, 1, h - 1), black);
 	}
 }
 
@@ -362,18 +362,18 @@
 
 	if (get_bar_size() > 0) {
 		dst.brighten_rect  //  bottom edge
-		   (Rectf(get_x_gap(), get_h() / 2.f, get_bar_size(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(get_x_gap(), get_h() / 2, get_bar_size(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		dst.brighten_rect  //  right edge
-		   (Rectf(get_x_gap() + get_bar_size() - 2, get_y_gap(), 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		   (Recti(get_x_gap() + get_bar_size() - 2, get_y_gap(), 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 
 		//  top edge
-		dst.fill_rect(Rectf(get_x_gap(), get_y_gap(), get_bar_size() - 1, 1), black);
-		dst.fill_rect(Rectf(get_x_gap(), get_y_gap() + 1, get_bar_size() - 2, 1), black);
+		dst.fill_rect(Recti(get_x_gap(), get_y_gap(), get_bar_size() - 1, 1), black);
+		dst.fill_rect(Recti(get_x_gap(), get_y_gap() + 1, get_bar_size() - 2, 1), black);
 	}
 
 	//  left edge
-	dst.fill_rect(Rectf(get_x_gap(), get_y_gap(), 1, 4), black);
-	dst.fill_rect(Rectf(get_x_gap() + 1, get_y_gap(), 1, 3), black);
+	dst.fill_rect(Recti(get_x_gap(), get_y_gap(), 1, 4), black);
+	dst.fill_rect(Recti(get_x_gap() + 1, get_y_gap(), 1, 3), black);
 
 	draw_cursor(dst, cursor_pos_, 0, cursor_size_, get_h());
 }
@@ -435,17 +435,17 @@
 	RGBAColor black(0, 0, 0, 255);
 
 	dst.brighten_rect  //  right edge
-	   (Rectf(get_w() / 2.f, get_y_gap(), 2, get_bar_size()), BUTTON_EDGE_BRIGHT_FACTOR);
+	   (Recti(get_w() / 2, get_y_gap(), 2, get_bar_size()), BUTTON_EDGE_BRIGHT_FACTOR);
 	dst.brighten_rect  //  bottom edge
-	   (Rectf(get_x_gap(), get_y_gap() + get_bar_size() - 2, 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+	   (Recti(get_x_gap(), get_y_gap() + get_bar_size() - 2, 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 
 	//  left edge
-	dst.fill_rect(Rectf(get_x_gap(), get_y_gap(), 1, get_bar_size() - 1), black);
-	dst.fill_rect(Rectf(get_x_gap() + 1, get_y_gap(), 1, get_bar_size() - 2), black);
+	dst.fill_rect(Recti(get_x_gap(), get_y_gap(), 1, get_bar_size() - 1), black);
+	dst.fill_rect(Recti(get_x_gap() + 1, get_y_gap(), 1, get_bar_size() - 2), black);
 
 	//  top edge
-	dst.fill_rect(Rectf(get_x_gap(), get_y_gap(), 4, 1), black);
-	dst.fill_rect(Rectf(get_x_gap(), get_y_gap() + 1, 3, 1), black);
+	dst.fill_rect(Recti(get_x_gap(), get_y_gap(), 4, 1), black);
+	dst.fill_rect(Recti(get_x_gap(), get_y_gap() + 1, 3, 1), black);
 
 	draw_cursor(dst, 0, cursor_pos_, get_w(), cursor_size_);
 }
@@ -540,8 +540,9 @@
 	for (uint32_t i = 0; i < labels.size(); i++) {
 		const Image* rendered_text =
 		   UI::g_fh1->render(as_condensed(labels[i], UI::Align::kCenter, UI_FONT_SIZE_SMALL - 2));
-		dst.blit(Vector2f(gap_1 + i * gap_n, get_h() - rendered_text->height()), rendered_text,
-		         BlendMode::UseAlpha, UI::Align::kCenter);
+		Vector2i point(gap_1 + i * gap_n, get_h() - rendered_text->height());
+		UI::correct_for_align(UI::Align::kCenter, rendered_text->width(), &point);
+		dst.blit(point, rendered_text, BlendMode::UseAlpha);
 	}
 }
 

=== modified file 'src/ui_basic/table.cc'
--- src/ui_basic/table.cc	2017-04-10 05:43:19 +0000
+++ src/ui_basic/table.cc	2017-04-22 16:16:31 +0000
@@ -220,7 +220,7 @@
 	uint32_t idx = scrollpos_ / lineheight;
 	int32_t y = 1 + idx * lineheight - scrollpos_ + headerheight_;
 
-	dst.brighten_rect(Rectf(0.f, 0.f, get_eff_w(), get_h()), ms_darken_value);
+	dst.brighten_rect(Recti(0, 0, get_eff_w(), get_h()), ms_darken_value);
 
 	while (idx < entry_records_.size()) {
 		if (y >= static_cast<int32_t>(get_h()))
@@ -230,7 +230,7 @@
 
 		if (idx == selection_ || multiselect_.count(idx)) {
 			assert(2 <= get_eff_w());
-			dst.brighten_rect(Rectf(1.f, y, get_eff_w() - 2, lineheight_), -ms_darken_value);
+			dst.brighten_rect(Recti(1, y, get_eff_w() - 2, lineheight_), -ms_darken_value);
 		}
 
 		Columns::size_type const nr_columns = columns_.size();
@@ -242,14 +242,14 @@
 			const Image* entry_picture = er.get_picture(i);
 			const std::string& entry_string = er.get_string(i);
 
-			Vector2f point(curx, y);
+			Vector2i point(curx, y);
 			int picw = 0;
 
 			if (entry_picture != nullptr) {
 				picw = entry_picture->width();
 				const int pich = entry_picture->height();
 
-				float draw_x = point.x;
+				int draw_x = point.x;
 
 				// We want a bit of margin
 				int max_pic_height = lineheight - 3;
@@ -263,7 +263,7 @@
 						if (i == nr_columns - 1 && scrollbar_->is_enabled()) {
 							draw_x = point.x + (curw - blit_width - scrollbar_->get_w()) / 2.f;
 						} else {
-							draw_x = point.x + (curw - blit_width) / 2.f;
+							draw_x = point.x + (curw - blit_width) / 2;
 						}
 					}
 
@@ -272,7 +272,7 @@
 					}
 
 					// Create the scaled image
-					dst.blitrect_scale(Rectf(draw_x, point.y + 1.f, blit_width, max_pic_height),
+					dst.blitrect_scale(Rectf(draw_x, point.y + 1, blit_width, max_pic_height),
 					                   entry_picture, Recti(0, 0, picw, pich), 1., BlendMode::UseAlpha);
 
 					// For text alignment below
@@ -282,12 +282,12 @@
 						if (i == nr_columns - 1 && scrollbar_->is_enabled()) {
 							draw_x = point.x + (curw - picw - scrollbar_->get_w()) / 2.f;
 						} else {
-							draw_x = point.x + (curw - picw) / 2.f;
+							draw_x = point.x + (curw - picw) / 2;
 						}
 					} else if (alignment == UI::Align::kRight) {
 						draw_x += curw - picw;
 					}
-					dst.blit(Vector2f(draw_x, point.y + (lineheight - pich) / 2.f), entry_picture);
+					dst.blit(Vector2i(draw_x, point.y + (lineheight - pich) / 2), entry_picture);
 				}
 				point.x += picw;
 			}

=== modified file 'src/ui_basic/tabpanel.cc'
--- src/ui_basic/tabpanel.cc	2017-03-04 09:14:37 +0000
+++ src/ui_basic/tabpanel.cc	2017-04-22 16:16:31 +0000
@@ -279,7 +279,7 @@
 		tab_width = tabs_[idx]->get_w();
 
 		if (highlight_ == idx) {
-			dst.brighten_rect(Rectf(x, 0, tab_width, kTabPanelButtonHeight), MOUSE_OVER_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(x, 0, tab_width, kTabPanelButtonHeight), MOUSE_OVER_BRIGHT_FACTOR);
 		}
 
 		assert(tabs_[idx]->pic);
@@ -300,46 +300,46 @@
 			   tabs_[idx]->pic, Recti(0, 0, tabs_[idx]->pic->width(), tabs_[idx]->pic->height()), 1,
 			   BlendMode::UseAlpha);
 		} else {
-			dst.blit(Vector2f(x + kTabPanelTextMargin,
+			dst.blit(Vector2i(x + kTabPanelTextMargin,
 			                  (kTabPanelButtonHeight - tabs_[idx]->pic->height()) / 2),
-			         tabs_[idx]->pic, BlendMode::UseAlpha, UI::Align::kLeft);
+			         tabs_[idx]->pic, BlendMode::UseAlpha);
 		}
 
 		// Draw top part of border
-		dst.brighten_rect(Rectf(x, 0, tab_width, 2), BUTTON_EDGE_BRIGHT_FACTOR);
-		dst.brighten_rect(Rectf(x, 2, 2, kTabPanelButtonHeight - 4), BUTTON_EDGE_BRIGHT_FACTOR);
-		dst.fill_rect(Rectf(x + tab_width - 2, 2, 1, kTabPanelButtonHeight - 4), black);
-		dst.fill_rect(Rectf(x + tab_width - 1, 1, 1, kTabPanelButtonHeight - 3), black);
+		dst.brighten_rect(Recti(x, 0, tab_width, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(x, 2, 2, kTabPanelButtonHeight - 4), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.fill_rect(Recti(x + tab_width - 2, 2, 1, kTabPanelButtonHeight - 4), black);
+		dst.fill_rect(Recti(x + tab_width - 1, 1, 1, kTabPanelButtonHeight - 3), black);
 
 		// Draw bottom part
 		if (active_ != idx)
 			dst.brighten_rect(
-			   Rectf(x, kTabPanelButtonHeight - 2, tab_width, 2), 2 * BUTTON_EDGE_BRIGHT_FACTOR);
+			   Recti(x, kTabPanelButtonHeight - 2, tab_width, 2), 2 * BUTTON_EDGE_BRIGHT_FACTOR);
 		else {
-			dst.brighten_rect(Rectf(x, kTabPanelButtonHeight - 2, 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
+			dst.brighten_rect(Recti(x, kTabPanelButtonHeight - 2, 2, 2), BUTTON_EDGE_BRIGHT_FACTOR);
 
-			dst.brighten_rect(Rectf(x + tab_width - 2, kTabPanelButtonHeight - 2, 2, 2),
+			dst.brighten_rect(Recti(x + tab_width - 2, kTabPanelButtonHeight - 2, 2, 2),
 			                  2 * BUTTON_EDGE_BRIGHT_FACTOR);
-			dst.fill_rect(Rectf(x + tab_width - 2, kTabPanelButtonHeight - 1, 1, 1), black);
-			dst.fill_rect(Rectf(x + tab_width - 2, kTabPanelButtonHeight - 2, 2, 1), black);
+			dst.fill_rect(Recti(x + tab_width - 2, kTabPanelButtonHeight - 1, 1, 1), black);
+			dst.fill_rect(Recti(x + tab_width - 2, kTabPanelButtonHeight - 2, 2, 1), black);
 		}
 	}
 
 	// draw the remaining separator
 	assert(x <= get_w());
-	dst.brighten_rect(Rectf(x + tab_width, kTabPanelButtonHeight - 2, get_w() - x, 2),
+	dst.brighten_rect(Recti(x + tab_width, kTabPanelButtonHeight - 2, get_w() - x, 2),
 	                  2 * BUTTON_EDGE_BRIGHT_FACTOR);
 
 	// Draw border around the main panel
 	if (border_type_ == TabPanel::Type::kBorder) {
 		//  left edge
-		dst.brighten_rect(Rectf(0, kTabPanelButtonHeight, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, kTabPanelButtonHeight, 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 		//  bottom edge
-		dst.fill_rect(Rectf(2, get_h() - 2, get_w() - 2, 1), black);
-		dst.fill_rect(Rectf(1, get_h() - 1, get_w() - 1, 1), black);
+		dst.fill_rect(Recti(2, get_h() - 2, get_w() - 2, 1), black);
+		dst.fill_rect(Recti(1, get_h() - 1, get_w() - 1, 1), black);
 		//  right edge
-		dst.fill_rect(Rectf(get_w() - 2, kTabPanelButtonHeight - 1, 1, get_h() - 2), black);
-		dst.fill_rect(Rectf(get_w() - 1, kTabPanelButtonHeight - 2, 1, get_h() - 1), black);
+		dst.fill_rect(Recti(get_w() - 2, kTabPanelButtonHeight - 1, 1, get_h() - 2), black);
+		dst.fill_rect(Recti(get_w() - 1, kTabPanelButtonHeight - 2, 1, get_h() - 1), black);
 	}
 }
 

=== modified file 'src/ui_basic/textarea.cc'
--- src/ui_basic/textarea.cc	2017-02-27 13:48:29 +0000
+++ src/ui_basic/textarea.cc	2017-04-22 16:16:31 +0000
@@ -125,10 +125,10 @@
  */
 void Textarea::draw(RenderTarget& dst) {
 	if (!text_.empty()) {
-		// Blit on pixel boundary (not float), so that the text is blitted pixel perfect.
-		Vector2f anchor(
+		Vector2i anchor(
 		   (align_ == Align::kCenter) ? get_w() / 2 : (align_ == UI::Align::kRight) ? get_w() : 0, 0);
-		dst.blit(anchor, rendered_text_, BlendMode::UseAlpha, align_);
+		UI::correct_for_align(align_, rendered_text_->width(), &anchor);
+		dst.blit(anchor, rendered_text_, BlendMode::UseAlpha);
 	}
 }
 

=== modified file 'src/ui_basic/window.cc'
--- src/ui_basic/window.cc	2017-02-27 13:48:29 +0000
+++ src/ui_basic/window.cc	2017-04-22 16:16:31 +0000
@@ -253,19 +253,19 @@
 		int32_t pos = HZ_B_CORNER_PIXMAP_LEN;
 
 		dst.blitrect  //  top left corner
-		   (Vector2f(0.f, 0.f), pic_top_, Recti(Vector2i(0, 0), pos, TP_B_PIXMAP_THICKNESS));
+		   (Vector2i(), pic_top_, Recti(Vector2i(0, 0), pos, TP_B_PIXMAP_THICKNESS));
 
 		//  top bar
 		static_assert(0 <= HZ_B_CORNER_PIXMAP_LEN, "assert(0 <= HZ_B_CORNER_PIXMAP_LEN) failed.");
 		for (; pos < hz_bar_end_minus_middle; pos += HZ_B_MIDDLE_PIXMAP_LEN)
 			dst.blitrect(
-			   Vector2f(pos, 0), pic_top_, Recti(Vector2i(HZ_B_CORNER_PIXMAP_LEN, 0),
+			   Vector2i(pos, 0), pic_top_, Recti(Vector2i(HZ_B_CORNER_PIXMAP_LEN, 0),
 			                                     HZ_B_MIDDLE_PIXMAP_LEN, TP_B_PIXMAP_THICKNESS));
 
 		// odd pixels of top bar and top right corner
 		const int32_t width = hz_bar_end - pos + HZ_B_CORNER_PIXMAP_LEN;
 		assert(0 <= HZ_B_TOTAL_PIXMAP_LEN - width);
-		dst.blitrect(Vector2f(pos, 0), pic_top_,
+		dst.blitrect(Vector2i(pos, 0), pic_top_,
 		             Recti(Vector2i(HZ_B_TOTAL_PIXMAP_LEN - width, 0), width, TP_B_PIXMAP_THICKNESS));
 	}
 
@@ -276,9 +276,10 @@
 		   autofit_ui_text(richtext_escape(title_), get_inner_w(), UI_FONT_CLR_FG, 13);
 
 		// Blit on pixel boundary (not float), so that the text is blitted pixel perfect.
-		Vector2f pos(get_lborder() + get_inner_w() / 2, TP_B_PIXMAP_THICKNESS / 2);
+		Vector2i pos(get_lborder() + get_inner_w() / 2, TP_B_PIXMAP_THICKNESS / 2);
+		UI::correct_for_align(UI::Align::kCenter, text->width(), &pos);
 		UI::center_vertically(text->height(), &pos);
-		dst.blit(pos, text, BlendMode::UseAlpha, UI::Align::kCenter);
+		dst.blit(pos, text, BlendMode::UseAlpha);
 	}
 
 	if (!is_minimal_) {
@@ -290,7 +291,7 @@
 
 			static_assert(0 <= VT_B_PIXMAP_THICKNESS, "assert(0 <= VT_B_PIXMAP_THICKNESS) failed.");
 			dst.blitrect  // left top thingy
-			   (Vector2f(0, TP_B_PIXMAP_THICKNESS), pic_lborder_,
+			   (Vector2i(0, TP_B_PIXMAP_THICKNESS), pic_lborder_,
 			    Recti(Vector2i(0, 0), VT_B_PIXMAP_THICKNESS, VT_B_THINGY_PIXMAP_LEN));
 
 			int32_t pos = TP_B_PIXMAP_THICKNESS + VT_B_THINGY_PIXMAP_LEN;
@@ -298,7 +299,7 @@
 			//  left bar
 			static_assert(0 <= VT_B_THINGY_PIXMAP_LEN, "assert(0 <= VT_B_THINGY_PIXMAP_LEN) failed.");
 			for (; pos < vt_bar_end_minus_middle; pos += VT_B_MIDDLE_PIXMAP_LEN)
-				dst.blitrect(Vector2f(0, pos), pic_lborder_,
+				dst.blitrect(Vector2i(0, pos), pic_lborder_,
 				             Recti(Vector2i(0, VT_B_THINGY_PIXMAP_LEN), VT_B_PIXMAP_THICKNESS,
 				                   VT_B_MIDDLE_PIXMAP_LEN));
 
@@ -306,7 +307,7 @@
 			const int32_t height = vt_bar_end - pos + VT_B_THINGY_PIXMAP_LEN;
 			assert(0 <= VT_B_TOTAL_PIXMAP_LEN - height);
 			dst.blitrect(
-			   Vector2f(0, pos), pic_lborder_,
+			   Vector2i(0, pos), pic_lborder_,
 			   Recti(Vector2i(0, VT_B_TOTAL_PIXMAP_LEN - height), VT_B_PIXMAP_THICKNESS, height));
 		}
 
@@ -314,7 +315,7 @@
 			const int32_t right_border_x = get_w() - VT_B_PIXMAP_THICKNESS;
 
 			dst.blitrect  // right top thingy
-			   (Vector2f(right_border_x, TP_B_PIXMAP_THICKNESS), pic_rborder_,
+			   (Vector2i(right_border_x, TP_B_PIXMAP_THICKNESS), pic_rborder_,
 			    Recti(Vector2i(0, 0), VT_B_PIXMAP_THICKNESS, VT_B_THINGY_PIXMAP_LEN));
 
 			int32_t pos = TP_B_PIXMAP_THICKNESS + VT_B_THINGY_PIXMAP_LEN;
@@ -322,14 +323,14 @@
 			//  right bar
 			static_assert(0 <= VT_B_THINGY_PIXMAP_LEN, "assert(0 <= VT_B_THINGY_PIXMAP_LEN) failed.");
 			for (; pos < vt_bar_end_minus_middle; pos += VT_B_MIDDLE_PIXMAP_LEN)
-				dst.blitrect(Vector2f(right_border_x, pos), pic_rborder_,
+				dst.blitrect(Vector2i(right_border_x, pos), pic_rborder_,
 				             Recti(Vector2i(0, VT_B_THINGY_PIXMAP_LEN), VT_B_PIXMAP_THICKNESS,
 				                   VT_B_MIDDLE_PIXMAP_LEN));
 
 			// odd pixels of right bar and right bottom thingy
 			const int32_t height = vt_bar_end - pos + VT_B_THINGY_PIXMAP_LEN;
 			dst.blitrect(
-			   Vector2f(right_border_x, pos), pic_rborder_,
+			   Vector2i(right_border_x, pos), pic_rborder_,
 			   Recti(Vector2i(0, VT_B_TOTAL_PIXMAP_LEN - height), VT_B_PIXMAP_THICKNESS, height));
 		}
 
@@ -337,19 +338,19 @@
 			int32_t pos = HZ_B_CORNER_PIXMAP_LEN;
 
 			dst.blitrect  //  bottom left corner
-			   (Vector2f(0, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
+			   (Vector2i(0, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
 			    Recti(Vector2i(0, 0), pos, BT_B_PIXMAP_THICKNESS));
 
 			//  bottom bar
 			for (; pos < hz_bar_end_minus_middle; pos += HZ_B_MIDDLE_PIXMAP_LEN)
-				dst.blitrect(Vector2f(pos, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
+				dst.blitrect(Vector2i(pos, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
 				             Recti(Vector2i(HZ_B_CORNER_PIXMAP_LEN, 0), HZ_B_MIDDLE_PIXMAP_LEN,
 				                   BT_B_PIXMAP_THICKNESS));
 
 			// odd pixels of bottom bar and bottom right corner
 			const int32_t width = hz_bar_end - pos + HZ_B_CORNER_PIXMAP_LEN;
 			dst.blitrect(
-			   Vector2f(pos, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
+			   Vector2i(pos, get_h() - BT_B_PIXMAP_THICKNESS), pic_bottom_,
 			   Recti(Vector2i(HZ_B_TOTAL_PIXMAP_LEN - width, 0), width, BT_B_PIXMAP_THICKNESS));
 		}
 	}

=== modified file 'src/wui/chatoverlay.cc'
--- src/wui/chatoverlay.cc	2017-01-25 18:55:59 +0000
+++ src/wui/chatoverlay.cc	2017-04-22 16:16:31 +0000
@@ -183,10 +183,10 @@
 	const int width = std::min<int>(get_w(), im->width());
 
 	if (!m->transparent_) {
-		dst.fill_rect(Rectf(0, top, width, height), RGBAColor(50, 50, 50, 128), BlendMode::Default);
+		dst.fill_rect(Recti(0, top, width, height), RGBAColor(50, 50, 50, 128), BlendMode::Default);
 	}
 	int32_t topcrop = im->height() - height;
 	Recti cropRect(0, topcrop, width, height);
 
-	dst.blitrect(Vector2f(0, top), im, cropRect);
+	dst.blitrect(Vector2i(0, top), im, cropRect);
 }

=== modified file 'src/wui/game_tips.cc'
--- src/wui/game_tips.cc	2017-01-25 18:55:59 +0000
+++ src/wui/game_tips.cc	2017-04-22 16:16:31 +0000
@@ -107,11 +107,11 @@
 
 	uint16_t w = pic_background->width();
 	uint16_t h = pic_background->height();
-	Vector2f pt((g_gr->get_xres() - w) / 2, (g_gr->get_yres() - h) / 2);
-	Rectf tips_area(pt, w, h);
+	Vector2i pt((g_gr->get_xres() - w) / 2, (g_gr->get_yres() - h) / 2);
+	Recti tips_area(pt, w, h);
 	rt.blit(pt, pic_background);
 
 	const Image* rendered_text = UI::g_fh1->render(as_game_tip(tips_[index].text), tips_area.w);
-	rt.blit(tips_area.center() - Vector2f(rendered_text->width() / 2, rendered_text->height() / 2),
+	rt.blit(tips_area.center().cast<int>() - Vector2i(rendered_text->width() / 2, rendered_text->height() / 2),
 	        rendered_text);
 }

=== modified file 'src/wui/inputqueuedisplay.cc'
--- src/wui/inputqueuedisplay.cc	2017-01-25 18:55:59 +0000
+++ src/wui/inputqueuedisplay.cc	2017-04-22 16:16:31 +0000
@@ -131,12 +131,12 @@
 	uint32_t nr_inputs_to_draw = std::min(queue_->get_filled(), cache_size_);
 	uint32_t nr_empty_to_draw = cache_size_ - nr_inputs_to_draw;
 
-	Vector2f point;
+	Vector2i point;
 	point.x = Border + (show_only_ ? 0 : CellWidth + CellSpacing);
 	point.y = Border + (total_height_ - 2 * Border - WARE_MENU_PIC_HEIGHT) / 2;
 
 	for (; nr_inputs_to_draw; --nr_inputs_to_draw, point.x += CellWidth + CellSpacing) {
-		dst.blitrect(Vector2f(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()),
+		dst.blitrect(Vector2i(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()),
 		             BlendMode::UseAlpha);
 	}
 	for (; nr_empty_to_draw; --nr_empty_to_draw, point.x += CellWidth + CellSpacing) {

=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc	2017-03-03 18:13:55 +0000
+++ src/wui/interactive_base.cc	2017-04-22 16:16:31 +0000
@@ -358,8 +358,7 @@
 		if (is_game) {
 			const std::string gametime(gametimestring(egbase().get_gametime(), true));
 			const std::string gametime_text = as_condensed(gametime);
-			dst.blit(Vector2f(5, 5), UI::g_fh1->render(gametime_text), BlendMode::UseAlpha,
-			         UI::Align::kLeft);
+			dst.blit(Vector2i(5, 5), UI::g_fh1->render(gametime_text), BlendMode::UseAlpha);
 
 			static boost::format node_format("(%i, %i)");
 			node_text = as_condensed((node_format % sel_.pos.node.x % sel_.pos.node.y).str());
@@ -370,9 +369,9 @@
 		}
 
 		const Image* rendered_text = UI::g_fh1->render(node_text);
-
-		dst.blit(Vector2f(get_w() - 5, get_h() - rendered_text->height() - 5), rendered_text,
-		         BlendMode::UseAlpha, UI::Align::kRight);
+		Vector2i point(get_w() - 5, get_h() - rendered_text->height() - 5);
+		UI::correct_for_align(UI::Align::kRight, rendered_text->width(), &point);
+		dst.blit(point, rendered_text, BlendMode::UseAlpha);
 	}
 
 	// Blit FPS when playing a game in debug mode.
@@ -380,8 +379,8 @@
 		static boost::format fps_format("%5.1f fps (avg: %5.1f fps)");
 		const Image* rendered_text = UI::g_fh1->render(as_condensed(
 		   (fps_format % (1000.0 / frametime_) % (1000.0 / (avg_usframetime_ / 1000))).str()));
-		dst.blit(Vector2f((get_w() - rendered_text->width()) / 2, 5), rendered_text,
-		         BlendMode::UseAlpha, UI::Align::kLeft);
+		dst.blit(Vector2i((get_w() - rendered_text->width()) / 2, 5), rendered_text,
+		         BlendMode::UseAlpha);
 	}
 }
 

=== modified file 'src/wui/interactive_gamebase.cc'
--- src/wui/interactive_gamebase.cc	2017-02-28 16:00:20 +0000
+++ src/wui/interactive_gamebase.cc	2017-04-22 16:16:31 +0000
@@ -126,8 +126,10 @@
 		}
 
 		if (!game_speed.empty()) {
-			dst.blit(Vector2f(get_w() - 5, 5), UI::g_fh1->render(game_speed), BlendMode::UseAlpha,
-			         UI::Align::kRight);
+			Vector2i point(get_w() - 5, 5);
+			const Image* rendered_speed = UI::g_fh1->render(game_speed);
+			UI::correct_for_align(UI::Align::kRight, rendered_speed->width(), &point);
+			dst.blit(point, rendered_speed, BlendMode::UseAlpha);
 		}
 	}
 }

=== modified file 'src/wui/itemwaresdisplay.cc'
--- src/wui/itemwaresdisplay.cc	2017-01-25 18:55:59 +0000
+++ src/wui/itemwaresdisplay.cc	2017-04-22 16:16:31 +0000
@@ -98,7 +98,7 @@
 void ItemWaresDisplay::draw(RenderTarget& dst) {
 	const Widelands::TribeDescr& tribe(player().tribe());
 
-	dst.fill_rect(Rectf(0, 0, get_w(), get_h()), RGBAColor(0, 0, 0, 0));
+	dst.fill_rect(Recti(0, 0, get_w(), get_h()), RGBAColor(0, 0, 0, 0));
 
 	for (uint32_t idx = 0; idx < items_.size(); ++idx) {
 		const Item& it = items_[idx];
@@ -117,7 +117,7 @@
 		} else {
 			y += IWD_WareBaseLine;
 			if (tribe.get_ware_descr(it.index)->icon())
-				dst.blit(Vector2f(x, y), tribe.get_ware_descr(it.index)->icon());
+				dst.blit(Vector2i(x, y), tribe.get_ware_descr(it.index)->icon());
 		}
 	}
 }

=== modified file 'src/wui/minimap.cc'
--- src/wui/minimap.cc	2017-02-12 09:10:57 +0000
+++ src/wui/minimap.cc	2017-04-22 16:16:31 +0000
@@ -52,7 +52,7 @@
 void MiniMap::View::draw(RenderTarget& dst) {
 	minimap_image_ = draw_minimap(ibase_.egbase(), ibase_.get_player(), view_area_, *minimap_type_,
 	                              *minimap_layers_ | MiniMapLayer::ViewWindow);
-	dst.blit(Vector2f(), minimap_image_.get());
+	dst.blit(Vector2i(), minimap_image_.get());
 }
 
 /*

=== modified file 'src/wui/plot_area.cc'
--- src/wui/plot_area.cc	2017-02-24 19:22:36 +0000
+++ src/wui/plot_area.cc	2017-04-22 16:16:31 +0000
@@ -176,12 +176,13 @@
  */
 void draw_value(const string& value,
                 const RGBColor& color,
-                const Vector2f& pos,
+                const Vector2i& pos,
                 RenderTarget& dst) {
 	const Image* pic = UI::g_fh1->render(ytick_text_style(value, color));
-	Vector2f point(pos);  // Un-const this
+	Vector2i point(pos);  // Un-const this
+	UI::correct_for_align(UI::Align::kRight, pic->width(), &point);
 	UI::center_vertically(pic->height(), &point);
-	dst.blit(point, pic, BlendMode::UseAlpha, UI::Align::kRight);
+	dst.blit(point, pic, BlendMode::UseAlpha);
 }
 
 /**
@@ -254,9 +255,10 @@
 		// over the number, not to the left
 		const Image* xtick = UI::g_fh1->render(
 		   xtick_text_style((boost::format("-%u ") % (max_x / how_many_ticks * i)).str()));
-		Vector2f pos(posx, inner_h - kSpaceBottom + 10);
+		Vector2i pos(posx, inner_h - kSpaceBottom + 10);
+		UI::correct_for_align(UI::Align::kCenter, xtick->width(), &pos);
 		UI::center_vertically(xtick->height(), &pos);
-		dst.blit(pos, xtick, BlendMode::UseAlpha, UI::Align::kCenter);
+		dst.blit(pos, xtick, BlendMode::UseAlpha);
 
 		posx -= sub;
 	}
@@ -272,9 +274,9 @@
 
 	//  print the used unit
 	const Image* xtick = UI::g_fh1->render(xtick_text_style(get_generic_unit_name(unit)));
-	Vector2f pos(2, kSpacing + 2);
+	Vector2i pos(2, kSpacing + 2);
 	UI::center_vertically(xtick->height(), &pos);
-	dst.blit(pos, xtick, BlendMode::UseAlpha, UI::Align::kLeft);
+	dst.blit(pos, xtick, BlendMode::UseAlpha);
 }
 
 }  // namespace
@@ -460,7 +462,7 @@
 
 	//  print the maximal value into the top right corner
 	draw_value(yscale_label, RGBColor(60, 125, 0),
-	           Vector2f(get_inner_w() - kSpaceRight - 2, kSpacing + 2), dst);
+	           Vector2i(get_inner_w() - kSpaceRight - 2, kSpacing + 2), dst);
 
 	//  plot the pixels
 	for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
@@ -646,7 +648,7 @@
 
 	// Print the min value
 	draw_value((boost::format("-%u") % (highest_scale_)).str(), RGBColor(125, 0, 0),
-	           Vector2f(get_inner_w() - kSpaceRight - 2, get_inner_h() - kSpacing - 15), dst);
+	           Vector2i(get_inner_w() - kSpaceRight - 2, get_inner_h() - kSpacing - 15), dst);
 
 	// draw zero line
 	dst.draw_line_strip({Vector2f(get_inner_w() - kSpaceRight, yoffset),

=== modified file 'src/wui/soldierlist.cc'
--- src/wui/soldierlist.cc	2017-02-25 13:27:40 +0000
+++ src/wui/soldierlist.cc	2017-04-22 16:16:31 +0000
@@ -281,11 +281,11 @@
 	uint32_t fullrows = capacity / kMaxColumns;
 
 	if (fullrows) {
-		dst.fill_rect(Rectf(0.f, 0.f, get_w(), icon_height_ * fullrows), RGBAColor(0, 0, 0, 0));
+		dst.fill_rect(Recti(0, 0, get_w(), icon_height_ * fullrows), RGBAColor(0, 0, 0, 0));
 	}
 	if (capacity % kMaxColumns) {
 		dst.fill_rect(
-		   Rectf(0.f, icon_height_ * fullrows, icon_width_ * (capacity % kMaxColumns), icon_height_),
+		   Recti(0, icon_height_ * fullrows, icon_width_ * (capacity % kMaxColumns), icon_height_),
 		   RGBAColor(0, 0, 0, 0));
 	}
 
@@ -297,7 +297,7 @@
 
 		constexpr float kNoZoom = 1.f;
 		soldier->draw_info_icon(
-		   icon.pos.cast<float>() + Vector2f(kIconBorder, kIconBorder), kNoZoom, false, &dst);
+		   icon.pos + Vector2i(kIconBorder, kIconBorder), kNoZoom, false, &dst);
 	}
 }
 

=== modified file 'src/wui/warehousewindow.cc'
--- src/wui/warehousewindow.cc	2017-02-27 18:28:39 +0000
+++ src/wui/warehousewindow.cc	2017-04-22 16:16:31 +0000
@@ -94,7 +94,7 @@
 	}
 	assert(pic != nullptr);
 
-	dst.blit(ware_position(ware).cast<float>(), pic);
+	dst.blit(ware_position(ware), pic);
 }
 
 /**

=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc	2017-02-24 08:07:50 +0000
+++ src/wui/waresdisplay.cc	2017-04-22 16:16:31 +0000
@@ -320,20 +320,20 @@
 	                                                        "images/wui/ware_list_bg.png");
 	uint16_t w = bgpic->width();
 
-	const Vector2f p = ware_position(id).cast<float>();
+	const Vector2i p = ware_position(id);
 	dst.blit(p, bgpic);
 
 	const Image* icon = type_ == Widelands::wwWORKER ? tribe_.get_worker_descr(id)->icon() :
 	                                                   tribe_.get_ware_descr(id)->icon();
 
-	dst.blit(p + Vector2f((w - WARE_MENU_PIC_WIDTH) / 2.f, 1.f), icon);
+	dst.blit(p + Vector2i((w - WARE_MENU_PIC_WIDTH) / 2, 1), icon);
 
-	dst.fill_rect(Rectf(p + Vector2f(0.f, WARE_MENU_PIC_HEIGHT), w, WARE_MENU_INFO_SIZE),
+	dst.fill_rect(Recti(p + Vector2i(0, WARE_MENU_PIC_HEIGHT), w, WARE_MENU_INFO_SIZE),
 	              info_color_for_ware(id));
 
 	const Image* text = UI::g_fh1->render(as_waresinfo(info_for_ware(id)));
 	if (text)  // might be zero when there is no info text.
-		dst.blit(p + Vector2f(w - text->width() - 1,
+		dst.blit(p + Vector2i(w - text->width() - 1,
 		                      WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 1 - text->height()),
 		         text);
 }


Follow ups