diff --git a/src/simutrans/dataobj/translator.cc b/src/simutrans/dataobj/translator.cc
index c0c740cfc..3bbb3feb1 100644
--- a/src/simutrans/dataobj/translator.cc
+++ b/src/simutrans/dataobj/translator.cc
@@ -13,6 +13,7 @@
 #include "../sys/simsys.h"
 #include "../simtypes.h"
 #include "../display/simgraph.h" // for unicode stuff
+#include "../display/font.h"
 #include "translator.h"
 #include "loadsave.h"
 #include "environment.h"
@@ -595,7 +596,7 @@ void translator::set_language(int lang)
 		single_instance.current_lang = lang;
 		current_langinfo = langs+lang;
 		env_t::language_iso = langs[lang].iso;
-		current_langinfo->ellipsis_width = gfx->calc_text_width( translate("...") );
+		current_langinfo->ellipsis_width = font_t::default_font->calc_text_width( translate("..."));
 		DBG_MESSAGE("translator::set_language()", "%s, unicode %d", langs[lang].name, true);
 	}
 	else {
diff --git a/src/simutrans/display/font.cc b/src/simutrans/display/font.cc
index 1543b4759..ff77e093e 100644
--- a/src/simutrans/display/font.cc
+++ b/src/simutrans/display/font.cc
@@ -22,6 +22,11 @@
 #include <cstring>
 
 
+static font_t default_font;
+
+const font_t *font_t::default_font = &::default_font;
+
+
 font_t::glyph_t::glyph_t() :
 	height(0),
 	width(0),
@@ -464,6 +469,18 @@ bool font_t::load_from_file(const char *srcfilename)
 		print_debug();
 	}
 #endif
+
+	if (ok) {
+		// find default number width
+		const char* digits = "0123456789";
+		this->number_width = 0;
+
+		while (*digits) {
+			scr_coord_val w = this->get_glyph_advance(*digits++);
+			this->number_width = std::max(this->number_width, w);
+		}
+	}
+
 	return ok;
 #else
 	return true;
@@ -497,3 +514,141 @@ const font_t::glyph_t& font_t::get_glyph(utf32 c) const
 	}
 	return dummy;
 }
+
+
+const font_t *font_t::load_default_font(const char *fname, bool reload)
+{
+	font_t loaded_fnt;
+
+	if(  fname == NULL  ) {
+		dbg->error( "font_t::load_default_font", "NULL filename" );
+		return nullptr;
+	}
+
+	// skip reloading if already in memory, if bdf font
+	if(  !reload  &&  ::default_font.is_loaded()  &&  strcmp( ::default_font.get_fname(), fname ) == 0  ) {
+		return nullptr;
+	}
+
+	if(  loaded_fnt.load_from_file(fname)  ) {
+		::default_font = loaded_fnt;
+
+#if COLOUR_DEPTH != 0
+		env_t::fontname = fname;
+#endif
+
+		return &::default_font;
+	}
+
+	return nullptr;
+}
+
+
+utf32 font_t::get_next_char_with_metrics(const char* &text, unsigned char &byte_length, scr_coord_val &pixel_width) const
+{
+	size_t len = 0;
+	utf32 const char_code = utf8_decoder_t::decode((utf8 const *)text, len);
+
+	if(  char_code==UNICODE_NUL  ||  char_code == '\n') {
+		// case : end of text reached -> do not advance text pointer
+		// also stop at linebreaks
+		byte_length = 0;
+		pixel_width = 0;
+		return 0;
+	}
+	else {
+		text += len;
+		byte_length = (uint8)len;
+		pixel_width = get_glyph_advance(char_code);
+	}
+	return char_code;
+}
+
+
+size_t font_t::calc_text_index_for_width(const char *text, scr_coord_val max_width) const
+{
+	size_t bytes_so_far = 0;
+
+	uint8         byte_length  = 0;
+	scr_coord_val pixel_width  = 0;
+	scr_coord_val width_so_far = 0;
+
+	const char *tmp_text = text;
+	while(  this->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  && (width_so_far+pixel_width) <= max_width  ) {
+		width_so_far += pixel_width;
+		bytes_so_far += byte_length;
+	}
+
+	return bytes_so_far;
+}
+
+
+utf32 font_t::get_prev_char_with_metrics(const char* &text, const char *const text_start, unsigned char &byte_length, scr_coord_val &pixel_width) const
+{
+	if(  text<=text_start  ) {
+		// case : start of text reached or passed -> do not move the pointer backwards
+		byte_length = 0;
+		pixel_width = 0;
+		return 0;
+	}
+
+	utf32 char_code;
+	// determine the start of the previous logical character
+	do {
+		--text;
+	} while (  text>text_start  &&  (*text & 0xC0)==0x80  );
+
+	size_t len = 0;
+	char_code = utf8_decoder_t::decode((utf8 const *)text, len);
+	byte_length = (uint8)len;
+	pixel_width = this->get_glyph_advance(char_code);
+
+	return char_code;
+}
+
+
+scr_coord_val font_t::calc_text_width_n(const char *text, size_t len) const
+{
+	uint8 byte_length = 0;
+	scr_coord_val pixel_width = 0;
+	size_t idx = 0;
+	scr_coord_val width = 0;
+
+	while (this->get_next_char_with_metrics(text, byte_length, pixel_width)  &&  idx < len) {
+		width += pixel_width;
+		idx += byte_length;
+	}
+	return width;
+}
+
+
+scr_size font_t::calc_multiline_text_size(const char *text) const
+{
+	int width = 0;
+	bool last_cr = false;
+
+	scr_size size{0,0};
+
+	const utf8 *p = reinterpret_cast<const utf8 *>(text);
+	while (const utf32 iUnicode = utf8_decoder_t::decode(p)) {
+
+		if(  iUnicode == '\n'  ) {
+			// new line: record max width
+			size.w = max( size.w, width );
+			size.h += LINESPACE;
+			width = 0;
+			last_cr = true;
+			continue;
+		}
+		last_cr = false;
+		width += this->get_glyph_advance(iUnicode);
+	}
+
+	size.w = max( size.w, width );
+	if (!last_cr) {
+		// extra CR of the last was not already a CR
+		size.h += LINESPACE;
+	}
+
+	return size;
+}
diff --git a/src/simutrans/display/font.h b/src/simutrans/display/font.h
index 7de7a179b..d8ff1f98c 100644
--- a/src/simutrans/display/font.h
+++ b/src/simutrans/display/font.h
@@ -7,12 +7,15 @@
 #define DISPLAY_FONT_H
 
 
+#include "scr_coord.h"
 #include "../simtypes.h"
 #include "../utils/unicode.h"
 
+
 #include <stdio.h>
 #include <vector>
 
+
 /**
  * Terminology:
  *  - glyph:        display data of a single character
@@ -38,6 +41,17 @@ public:
 		sint16 left;
 	};
 
+private:
+	// a font height of zero could cause division by zero errors, even though it should not be used in a server
+	sint16 linespace = 1;
+	sint16 ascent = 0;
+	sint16 descent = 0;
+	scr_coord_val number_width;
+
+	std::vector<glyph_t> glyphs;
+
+	char fname[PATH_MAX];
+
 public:
 	font_t();
 
@@ -53,9 +67,6 @@ public:
 	sint16 get_linespace() const { return linespace; }
 	sint16 get_ascent() const { return ascent; }
 
-	/// @returns true if this is a valid (defined) glyph
-	bool is_valid_glyph(utf32 c) const { return  is_loaded()  &&  c < get_num_glyphs()  &&  glyphs[c].advance != 0xFF;  }
-
 	/// @returns size in pixels between the start of this glyph and the next glyph
 	sint16 get_glyph_advance(utf32 c) const;
 
@@ -72,13 +83,62 @@ private:
 
 	uint32 get_num_glyphs() const { return glyphs.size(); }
 
-private:
-	char fname[PATH_MAX];
-	sint16 linespace;
-	sint16 ascent;
-	sint16 descent;
-public:	// for simgraph has_character()
-	std::vector<glyph_t> glyphs;
+public:
+	//
+	// Font rendering and glyph metrics
+	//
+
+	/// returns true if this is a valid character for this font
+	bool has_glyph_for_character(utf32 c) const { return is_loaded()  &&  c < get_num_glyphs()  &&  glyphs[c].advance != 0xFF; }
+
+	scr_coord_val get_char_width(utf32 c) const { return this->get_glyph_advance(c); }
+	scr_coord_val get_number_width() const { return number_width; }
+
+	/**
+	 * For the next logical character in the text, returns the character code
+	 * as well as retrieves the char byte count and the screen pixel width
+	 * CAUTION : The text pointer advances to point to the next logical character
+	 */
+	utf32 get_next_char_with_metrics(const char *&text_iter, unsigned char &byte_length, scr_coord_val &pixel_width) const;
+
+	/**
+	 * For the previous logical character in the text, returns the character code
+	 * as well as retrieves the char byte count and the screen pixel width
+	 * CAUTION : The text pointer recedes to point to the previous logical character
+	 */
+	utf32 get_prev_char_with_metrics(const char *&text_iter, const char *const text_start, unsigned char &byte_length, scr_coord_val &pixel_width) const;
+
+	/// Calculates the screen width in pixels of a UTF-8 encoded string.
+	/// extended for universal font routines with unicode support
+	/// @param len number of bytes in @p text, or -1 if @p text is null-terminated.
+	scr_coord_val calc_text_width_n(const char *text, size_t len) const;
+
+	inline scr_coord_val calc_text_width(const char *text) const { return calc_text_width_n(text, 0x7FFFu); }
+
+	/// @returns Size of the bounding box which contains the UTF-8 encoded single- or multiline @p text
+	scr_size calc_multiline_text_size(const char *text) const;
+
+	/// Returns the byte offset of the last character that would fit within the width
+	/// If an ellipsis len is given, it will only return the last character up to this length if the full length cannot be fitted
+	/// @returns index of next character. if text[index]==0 the whole string fits
+	size_t calc_text_index_for_width(const char *text, scr_coord_val max_width) const;
+
+public:
+	static const font_t *default_font;
+
+	/// Loads the default font from @p filename
+	/// @param force_reload if true forces reload
+	/// @returns the font on success, or NULL on failure
+	static const font_t *load_default_font(const char *filename, bool force_reload);
 };
 
+
+//
+// Variables required for layouting
+//
+
+#define LINEASCENT (font_t::default_font->get_ascent())
+#define LINESPACE  (font_t::default_font->get_linespace())
+
+
 #endif
diff --git a/src/simutrans/display/simgraph.cc b/src/simutrans/display/simgraph.cc
index 24c7744d4..c0284b284 100644
--- a/src/simutrans/display/simgraph.cc
+++ b/src/simutrans/display/simgraph.cc
@@ -11,11 +11,6 @@
 
 const simgraph_t *gfx;
 
-scr_coord_val default_font_ascent = 0;
-
-// a font height of zero could cause division by zero errors, even though it should not be used in a server
-scr_coord_val default_font_linespace = 1;
-
 
 const simgraph_t *simgraph_select(simgraph_type_t preferred_type)
 {
diff --git a/src/simutrans/display/simgraph.h b/src/simutrans/display/simgraph.h
index a475d3809..5fe8bfef3 100644
--- a/src/simutrans/display/simgraph.h
+++ b/src/simutrans/display/simgraph.h
@@ -15,6 +15,7 @@
 
 
 class image_t;
+class font_t;
 
 
 /**
@@ -159,10 +160,6 @@ struct simgraph_t
 
 	void (*on_window_resized)(scr_size new_window_size);
 
-	/// Loads the font, returns the number of characters in it
-	/// @param reload if true forces reload
-	bool (*load_font)(const char *fname, bool reload /*=false*/);
-
 	/// Returns the number of currently registered images.
 	image_id (*get_image_count)();
 
@@ -275,81 +272,51 @@ struct simgraph_t
 	void (*draw_array)(scr_coord_val xp, scr_coord_val yp, scr_coord_val w, scr_coord_val h, const PIXVAL *arr);
 
 
-	//
-	// Font stuff and glyph metrics
-	// TODO this should maybe be moved somewhere else
-	//
-
-	/// returns true if this is a valid character for the currently loaded font
-	bool (*font_has_character)( utf16 char_code );
-
-	scr_coord_val (*get_char_width)(utf32 c);
-	scr_coord_val (*get_number_width)();
-
-	/**
-	 * For the next logical character in the text, returns the character code
-	 * as well as retrieves the char byte count and the screen pixel width
-	 * CAUTION : The text pointer advances to point to the next logical character
-	 */
-	utf32 (*get_next_char_with_metrics)(const char *&text, unsigned char &byte_length, unsigned char &pixel_width);
-
-	/**
-	 * For the previous logical character in the text, returns the character code
-	 * as well as retrieves the char byte count and the screen pixel width
-	 * CAUTION : The text pointer recedes to point to the previous logical character
-	 */
-	utf32 (*get_prev_char_with_metrics)(const char *&text, const char *const text_start, unsigned char &byte_length, unsigned char &pixel_width);
-
-
 	//
 	// Text rendering
 	//
 
-	/// Calculates the screen width of a UTF-8 encoded string in pixels.
-	/// @param len number of bytes in @p text, or -1 if @p text is null-terminated.
-	scr_coord_val (*calc_text_width_n)(const char *text, size_t len);
+	/// Draws single-line text @p txt.
+	/// @param len Maximum number of bytes in @p txt to read, or -1 to read until the end of the string,
+	scr_coord_val (*draw_text_clipped_n)(scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, control_alignment_t flags, PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF);
 
-	inline scr_coord_val calc_text_width(const char *text) const { return calc_text_width_n(text, 0x7FFFu); }
-
-	/// @returns Size of the bounding box which contains the single- or multiline @p text
-	scr_size (*calc_multiline_text_size)(const char *text);
-
-	/// Returns the index of the last character that would fit within the width
-	/// If an ellipsis len is given, it will only return the last character up to this len if the full length cannot be fitted
-	/// @returns index of next character. if text[index]==0 the whole string fits
-	size_t (*calc_text_index_for_width)(const char *text, scr_coord_val max_width);
-
-	scr_coord_val (*draw_text_clipped_n)(scr_coord_val x, scr_coord_val y, const char* txt, control_alignment_t flags, PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF);
-
-	inline scr_coord_val draw_text_clipped(scr_coord_val x, scr_coord_val y, const char* txt, control_alignment_t flags, PIXVAL color, bool dirty) const
+	/// Like as @ref draw_text_clipped_n, but always reads until newline
+	/// or the end of the string (whichever occurs earlier)
+	inline scr_coord_val draw_text_clipped(scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, control_alignment_t flags, PIXVAL color, bool dirty) const
 	{
-		return draw_text_clipped_n(x, y, txt, flags | DT_CLIP, color, dirty, -1 CLIP_NUM_DEFAULT);
+		return draw_text_clipped_n(x, y, txt, font, flags | DT_CLIP, color, dirty, -1 CLIP_NUM_DEFAULT);
 	}
 
-	inline scr_coord_val draw_text(scr_coord_val x, scr_coord_val y, const char *txt, control_alignment_t flags, PIXVAL color, bool dirty) const
+	/// Like @ref draw_text_clipped, but does *not* clip to active clip rect.
+	inline scr_coord_val draw_text(scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, control_alignment_t flags, PIXVAL color, bool dirty) const
 	{
-		return draw_text_clipped_n(x, y, txt, flags, color, dirty, -1 CLIP_NUM_DEFAULT);
+		return draw_text_clipped_n(x, y, txt, font, flags, color, dirty, -1 CLIP_NUM_DEFAULT);
 	}
 
-	scr_coord_val (*draw_multiline_text)(scr_coord_val x, scr_coord_val y, const char *text, PIXVAL color);
+	/// Draws single- or multi-line text.
+	/// @param x,y Position of the top-left corner of the bounding box of @p text.
+	scr_coord_val (*draw_multiline_text)(scr_coord_val x, scr_coord_val y, const char *text, const font_t *font, PIXVAL color);
 
 	/// Display a string that is abbreviated by the (language specific) ellipsis character if too wide
-	/// If enough space is given, it just display the full string
-	void (*draw_text_ellipsis_shadowed)(scr_rect r, const char *text, int align, PIXVAL color, bool dirty, bool shadow, PIXVAL shadow_color);
+	/// If enough space is given, it just displays the full string
+	/// If @p shadow is @e true, this will draw a shadow offset (+1,+1) pixels behind the actual text.
+	/// Does not clip to active clip rect.
+	void (*draw_text_ellipsis_shadowed)(scr_rect r, const char *text, const font_t *font, int align, PIXVAL color, bool dirty, bool shadow, PIXVAL shadow_color);
 
-	void draw_text_ellipsis(scr_rect r, const char *text, int align, PIXVAL color, bool dirty) const
+	/// Like @ref draw_text_ellipsis_shadowed, but never draws the text shadow.
+	void draw_text_ellipsis(scr_rect r, const char *text, const font_t *font, int align, PIXVAL color, bool dirty) const
 	{
-		draw_text_ellipsis_shadowed(r, text, align, color, dirty, false, 0);
+		draw_text_ellipsis_shadowed(r, text, font, align, color, dirty, false, 0);
 	}
 
 	// compound painting routines
-	void (*draw_text_outlined)(scr_coord_val xpos, scr_coord_val ypos, PIXVAL text_color, PIXVAL shadow_color, const char *text, int dirty);
-	void (*draw_text_shadowed)(scr_coord_val xpos, scr_coord_val ypos, PIXVAL text_color, PIXVAL shadow_color, const char *text, int dirty);
+	void (*draw_text_outlined)(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, PIXVAL text_color, PIXVAL shadow_color, int dirty);
+	void (*draw_text_shadowed)(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, PIXVAL text_color, PIXVAL shadow_color, int dirty);
 
 	void (*draw_box3d)        (scr_coord_val x1, scr_coord_val y1, scr_coord_val w, scr_coord_val h, PIXVAL tl_color, PIXVAL rd_color, bool dirty);
 	void (*draw_box3d_clipped)(scr_coord_val x1, scr_coord_val y1, scr_coord_val w, scr_coord_val h, PIXVAL tl_color, PIXVAL rd_color);
 
-	void (*draw_textbox3d_clipped)(scr_coord_val xpos, scr_coord_val ypos, FLAGGED_PIXVAL ddd_farbe, FLAGGED_PIXVAL text_farbe, const char *text, int dirty  CLIP_NUM_DEF);
+	void (*draw_textbox3d_clipped)(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, FLAGGED_PIXVAL ddd_farbe, FLAGGED_PIXVAL text_farbe, int dirty  CLIP_NUM_DEF);
 
 	/// Draw a straight solid line.
 	void (*draw_line)       (scr_coord_val x, scr_coord_val y, scr_coord_val xx, scr_coord_val yy, PIXVAL color);
@@ -397,16 +364,4 @@ const simgraph_t *simgraph_select(simgraph_type_t preferred_type);
 /// Assign to this the output of simgraph_select
 extern const simgraph_t *gfx;
 
-
-//
-// Variables required for layouting
-//
-
-extern scr_coord_val default_font_ascent;
-extern scr_coord_val default_font_linespace;
-
-#define LINEASCENT (default_font_ascent)
-#define LINESPACE  (default_font_linespace)
-
-
 #endif
diff --git a/src/simutrans/display/simgraph0.cc b/src/simutrans/display/simgraph0.cc
index 9f9e87dc5..20be642d7 100644
--- a/src/simutrans/display/simgraph0.cc
+++ b/src/simutrans/display/simgraph0.cc
@@ -27,7 +27,6 @@ static bool            simgraph0_init                       (scr_size window_siz
 static bool            simgraph0_is_display_init            ();
 static void            simgraph0_exit                       ();
 static void            simgraph0_on_window_resized          (scr_size new_window_size);
-static bool            simgraph0_load_font                  (const char *fname, bool reload);
 static image_id        simgraph0_get_image_count            ();
 static image_id        simgraph0_register_image             (const image_t *image_in);
 static void            simgraph0_free_all_images_above      (image_id above );
@@ -65,22 +64,14 @@ static void            simgraph0_set_cursor_visible         (bool);
 static void            simgraph0_set_default_cursor         (int);
 static void            simgraph0_set_show_load_cursor       (bool);
 static void            simgraph0_draw_array                 (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, const PIXVAL *);
-static scr_coord_val   simgraph0_calc_text_width_n          (const char *, size_t);
-static scr_size        simgraph0_calc_multiline_text_size   (const char *);
-static size_t          simgraph0_calc_text_index_for_width  (const char *, scr_coord_val);
-static bool            simgraph0_font_has_character         (utf16 char_code);
-static utf32           simgraph0_get_next_char_with_metrics (const char* &text, unsigned char &byte_length, unsigned char &pixel_width);
-static utf32           simgraph0_get_prev_char_with_metrics (const char* &text, const char *const text_start, unsigned char &byte_length, unsigned char &pixel_width);
-static scr_coord_val   simgraph0_get_char_width             (utf32 c);
-static scr_coord_val   simgraph0_get_number_width           ();
-static scr_coord_val   simgraph0_draw_text_clipped_n        (scr_coord_val, scr_coord_val, const char*, control_alignment_t , const PIXVAL, bool, sint32  CLIP_NUM_DEF_NOUSE);
-static scr_coord_val   simgraph0_draw_multiline_text        (scr_coord_val, scr_coord_val, const char *, PIXVAL);
-static void            simgraph0_draw_text_ellipsis_shadowed(scr_rect, const char *, int, PIXVAL, bool, bool, PIXVAL);
-static void            simgraph0_draw_text_outlined         (scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int);
-static void            simgraph0_draw_text_shadowed         (scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int);
+static scr_coord_val   simgraph0_draw_text_clipped_n        (scr_coord_val, scr_coord_val, const char*, const font_t *, control_alignment_t , const PIXVAL, bool, sint32  CLIP_NUM_DEF_NOUSE);
+static scr_coord_val   simgraph0_draw_multiline_text        (scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL);
+static void            simgraph0_draw_text_ellipsis_shadowed(scr_rect, const char *, const font_t *, int, PIXVAL, bool, bool, PIXVAL);
+static void            simgraph0_draw_text_outlined         (scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int);
+static void            simgraph0_draw_text_shadowed         (scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int);
 static void            simgraph0_draw_box3d                 (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, bool);
 static void            simgraph0_draw_box3d_clipped         (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL, PIXVAL);
-static void            simgraph0_draw_textbox3d_clipped     (scr_coord_val, scr_coord_val, FLAGGED_PIXVAL, FLAGGED_PIXVAL, const char *, int  CLIP_NUM_DEF_NOUSE);
+static void            simgraph0_draw_textbox3d_clipped     (scr_coord_val, scr_coord_val, const char *, const font_t *, FLAGGED_PIXVAL, FLAGGED_PIXVAL, int  CLIP_NUM_DEF_NOUSE);
 static void            simgraph0_draw_line                  (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL);
 static void            simgraph0_draw_line_dotted           (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL);
 static void            simgraph0_draw_empty_circle          (scr_coord_val, scr_coord_val, int, const PIXVAL);
@@ -105,6 +96,7 @@ static void            simgraph0_clear_all_poly_clip        ();
 static void            simgraph0_activate_ribi_clip         (int);
 #endif
 
+static void            simgraph0_set_light_color            (int light_idx, rgb888_t day_light, rgb888_t night_light);
 
 
 simgraph_t g_simgraph0 = {
@@ -135,7 +127,6 @@ simgraph_t g_simgraph0 = {
 	/*.is_display_init             =*/ simgraph0_is_display_init,
 	/*.exit                        =*/ simgraph0_exit,
 	/*.on_window_resized           =*/ simgraph0_on_window_resized,
-	/*.load_font                   =*/ simgraph0_load_font,
 	/*.get_image_count             =*/ simgraph0_get_image_count,
 	/*.register_image              =*/ simgraph0_register_image,
 	/*.free_all_images_above       =*/ simgraph0_free_all_images_above,
@@ -173,14 +164,6 @@ simgraph_t g_simgraph0 = {
 	/*.set_default_cursor          =*/ simgraph0_set_default_cursor,
 	/*.set_show_load_cursor        =*/ simgraph0_set_show_load_cursor,
 	/*.draw_array                  =*/ simgraph0_draw_array,
-	/*.font_has_character          =*/ simgraph0_font_has_character,
-	/*.get_char_width              =*/ simgraph0_get_char_width,
-	/*.get_number_width            =*/ simgraph0_get_number_width,
-	/*.get_next_char_with_metrics  =*/ simgraph0_get_next_char_with_metrics,
-	/*.get_prev_char_with_metrics  =*/ simgraph0_get_prev_char_with_metrics,
-	/*.calc_text_width_n           =*/ simgraph0_calc_text_width_n,
-	/*.calc_multiline_text_size    =*/ simgraph0_calc_multiline_text_size,
-	/*.calc_text_index_for_width   =*/ simgraph0_calc_text_index_for_width,
 	/*.draw_text_clipped_n         =*/ simgraph0_draw_text_clipped_n,
 	/*.draw_multiline_text         =*/ simgraph0_draw_multiline_text,
 	/*.draw_text_ellipsis_shadowed =*/ simgraph0_draw_text_ellipsis_shadowed,
@@ -263,10 +246,6 @@ static void simgraph0_mark_img_dirty(image_id, scr_coord_val, scr_coord_val)
 {
 }
 
-static bool simgraph0_load_font(const char *, bool)
-{
-	return true;
-}
 
 static scr_size simgraph0_get_screen_size()
 {
@@ -424,58 +403,17 @@ static void simgraph0_draw_array(scr_coord_val, scr_coord_val, scr_coord_val, sc
 {
 }
 
-static scr_coord_val simgraph0_get_char_width(utf32)
-{
-	return 0;
-}
-
-static scr_coord_val simgraph0_get_number_width()
-{
-	return 0;
-}
-
-static utf32 simgraph0_get_next_char_with_metrics(const char* &, unsigned char &, unsigned char &)
-{
-	return 0;
-}
-
-static utf32 simgraph0_get_prev_char_with_metrics(const char* &, const char *const, unsigned char &, unsigned char &)
-{
-	return 0;
-}
-
-static bool simgraph0_font_has_character( utf16 )
-{
-	return false;
-}
-
-static size_t simgraph0_calc_text_index_for_width(const char *, scr_coord_val)
-{
-	return 0;
-}
-
-static scr_coord_val simgraph0_calc_text_width_n(const char*, size_t)
-{
-	return 0;
-}
-
-
-static scr_size simgraph0_calc_multiline_text_size(const char *)
-{
-	return { 0, 0 };
-}
-
 
-static scr_coord_val simgraph0_draw_text_clipped_n(scr_coord_val, scr_coord_val, const char*, control_alignment_t , const PIXVAL, bool, sint32  CLIP_NUM_DEF_NOUSE)
+static scr_coord_val simgraph0_draw_text_clipped_n(scr_coord_val, scr_coord_val, const char *, const font_t *, control_alignment_t , const PIXVAL, bool, sint32  CLIP_NUM_DEF_NOUSE)
 {
 	return 0;
 }
 
-static void simgraph0_draw_text_outlined(scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int)
+static void simgraph0_draw_text_outlined(scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int)
 {
 }
 
-static void simgraph0_draw_text_shadowed(scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int)
+static void simgraph0_draw_text_shadowed(scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int)
 {
 }
 
@@ -487,11 +425,11 @@ static void simgraph0_draw_box3d_clipped(scr_coord_val, scr_coord_val, scr_coord
 {
 }
 
-static void simgraph0_draw_textbox3d_clipped(scr_coord_val, scr_coord_val, FLAGGED_PIXVAL, FLAGGED_PIXVAL, const char *, int  CLIP_NUM_DEF_NOUSE)
+static void simgraph0_draw_textbox3d_clipped(scr_coord_val, scr_coord_val, const char *, const font_t *, FLAGGED_PIXVAL, FLAGGED_PIXVAL, int  CLIP_NUM_DEF_NOUSE)
 {
 }
 
-static scr_coord_val simgraph0_draw_multiline_text(scr_coord_val, scr_coord_val, const char *, PIXVAL)
+static scr_coord_val simgraph0_draw_multiline_text(scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL)
 {
 	return 0;
 }
@@ -572,7 +510,7 @@ static void simgraph0_draw_img_aligned(const image_id, scr_rect, int, bool)
 {
 }
 
-static void simgraph0_draw_text_ellipsis_shadowed( scr_rect, const char *, int, PIXVAL, bool, bool, PIXVAL)
+static void simgraph0_draw_text_ellipsis_shadowed( scr_rect, const char *, const font_t *, int, PIXVAL, bool, bool, PIXVAL)
 {
 }
 
diff --git a/src/simutrans/display/simgraph16.cc b/src/simutrans/display/simgraph16.cc
index b0215e74d..fced76691 100644
--- a/src/simutrans/display/simgraph16.cc
+++ b/src/simutrans/display/simgraph16.cc
@@ -30,7 +30,6 @@
 #include <cstdlib>
 #include <cstring>
 
-
 #ifdef _MSC_VER
 #	include <io.h>
 #	define W_OK 2
@@ -71,7 +70,6 @@ static int standard_pointer = -1;
 int old_my = -1;
 #endif
 
-
 /*
  * struct to hold the information about visible area
  * at screen line y
@@ -241,10 +239,6 @@ clipping_info_t clips;
 
 #define CR clips CLIP_NUM_INDEX
 
-static font_t default_font;
-
-// needed for resizing gui
-static int default_font_numberwidth = 0;
 
 
 #define RGBMAPSIZE (0x8000+LIGHT_COUNT+MAX_PLAYER_COUNT+1024 /* 343 transparent */)
@@ -506,7 +500,6 @@ static bool            simgraph16_init                       (scr_size window_si
 static bool            simgraph16_is_display_init            ();
 static void            simgraph16_exit                       ();
 static void            simgraph16_on_window_resized          (scr_size new_window_size);
-static bool            simgraph16_load_font                  (const char *fname, bool reload);
 static image_id        simgraph16_get_image_count            ();
 static image_id        simgraph16_register_image             (const image_t *image_in);
 static void            simgraph16_free_all_images_above      (image_id above );
@@ -544,22 +537,14 @@ static void            simgraph16_set_cursor_visible         (bool show);
 static void            simgraph16_set_default_cursor         (int cursor_id);
 static void            simgraph16_set_show_load_cursor       (bool show);
 static void            simgraph16_draw_array                 (scr_coord_val xp, scr_coord_val yp, scr_coord_val w, scr_coord_val h, const PIXVAL *arr);
-static scr_coord_val   simgraph16_calc_text_width_n          (const char *text, size_t len);
-static scr_size        simgraph16_calc_multiline_text_size   (const char *text);
-static size_t          simgraph16_calc_text_index_for_width  (const char *, scr_coord_val);
-static bool            simgraph16_font_has_character         (utf16 char_code);
-static utf32           simgraph16_get_next_char_with_metrics (const char* &text, unsigned char &byte_length, unsigned char &pixel_width);
-static utf32           simgraph16_get_prev_char_with_metrics (const char* &text, const char *const text_start, unsigned char &byte_length, unsigned char &pixel_width);
-static scr_coord_val   simgraph16_get_char_width             (utf32 c);
-static scr_coord_val   simgraph16_get_number_width           ();
-static scr_coord_val   simgraph16_draw_text_clipped_n        (scr_coord_val x, scr_coord_val y, const char* txt, control_alignment_t flags, const PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF);
-static scr_coord_val   simgraph16_draw_multiline_text        (scr_coord_val, scr_coord_val, const char *, PIXVAL);
-static void            simgraph16_draw_text_ellipsis_shadowed(scr_rect, const char *, int, PIXVAL, bool, bool, PIXVAL);
-static void            simgraph16_draw_text_outlined         (scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int);
-static void            simgraph16_draw_text_shadowed         (scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, const char *, int);
+static scr_coord_val   simgraph16_draw_text_clipped_n        (scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, control_alignment_t flags, const PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF);
+static scr_coord_val   simgraph16_draw_multiline_text        (scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, PIXVAL colour);
+static void            simgraph16_draw_text_ellipsis_shadowed(scr_rect, const char *, const font_t *, int, PIXVAL, bool, bool, PIXVAL);
+static void            simgraph16_draw_text_outlined         (scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int);
+static void            simgraph16_draw_text_shadowed         (scr_coord_val, scr_coord_val, const char *, const font_t *, PIXVAL, PIXVAL, int);
 static void            simgraph16_draw_box3d                 (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL, PIXVAL, bool);
 static void            simgraph16_draw_box3d_clipped         (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL, PIXVAL);
-static void            simgraph16_draw_textbox3d_clipped     (scr_coord_val, scr_coord_val, FLAGGED_PIXVAL, FLAGGED_PIXVAL, const char *, int  CLIP_NUM_DEF_NOUSE);
+static void            simgraph16_draw_textbox3d_clipped     (scr_coord_val, scr_coord_val, const char *, const font_t *, FLAGGED_PIXVAL, FLAGGED_PIXVAL, int  CLIP_NUM_DEF_NOUSE);
 static void            simgraph16_draw_line                  (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL);
 static void            simgraph16_draw_line_dotted           (scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, scr_coord_val, PIXVAL);
 static void            simgraph16_draw_empty_circle          (scr_coord_val, scr_coord_val, int, const PIXVAL);
@@ -581,13 +566,13 @@ static void            simgraph16_activate_ribi_clip         (int ribi  CLIP_NUM
 simgraph_t g_simgraph16 = {
 	/*.type                      =*/ SIMGRAPH_TYPE_SOFTWARE,
 
-	/*.tile_raster_width         =*/ 16, // zoomed
-	/*.base_tile_raster_width    =*/ 16, // original
-	/*.current_tile_raster_width =*/ 0,
-	/*.draw_normal               =*/ NULL,
-	/*.draw_color                =*/ NULL,
-	/*.draw_blend                =*/ NULL,
-	/*.draw_alpha                =*/ NULL,
+	/*.tile_raster_width           =*/ 16, // zoomed
+	/*.base_tile_raster_width      =*/ 16, // original
+	/*.current_tile_raster_width   =*/ 0,
+	/*.draw_normal                 =*/ NULL,
+	/*.draw_color                  =*/ NULL,
+	/*.draw_blend                  =*/ NULL,
+	/*.draw_alpha                  =*/ NULL,
 
 	/*.zoom_num =*/ { 2, 3, 4, 1, 3, 5, 1, 3, 1, 1 },
 	/*.zoom_den =*/ { 1, 2, 3, 1, 4, 8, 2, 8, 4, 8 },
@@ -607,7 +592,6 @@ simgraph_t g_simgraph16 = {
 	/*.is_display_init             =*/ simgraph16_is_display_init,
 	/*.exit                        =*/ simgraph16_exit,
 	/*.on_window_resized           =*/ simgraph16_on_window_resized,
-	/*.load_font                   =*/ simgraph16_load_font,
 	/*.get_image_count             =*/ simgraph16_get_image_count,
 	/*.register_image              =*/ simgraph16_register_image,
 	/*.free_all_images_above       =*/ simgraph16_free_all_images_above,
@@ -645,14 +629,6 @@ simgraph_t g_simgraph16 = {
 	/*.set_default_cursor          =*/ simgraph16_set_default_cursor,
 	/*.set_show_load_cursor        =*/ simgraph16_set_show_load_cursor,
 	/*.draw_array                  =*/ simgraph16_draw_array,
-	/*.font_has_character          =*/ simgraph16_font_has_character,
-	/*.get_char_width              =*/ simgraph16_get_char_width,
-	/*.get_number_width            =*/ simgraph16_get_number_width,
-	/*.get_next_char_with_metrics  =*/ simgraph16_get_next_char_with_metrics,
-	/*.get_prev_char_with_metrics  =*/ simgraph16_get_prev_char_with_metrics,
-	/*.calc_text_width_n           =*/ simgraph16_calc_text_width_n,
-	/*.calc_multiline_text_size    =*/ simgraph16_calc_multiline_text_size,
-	/*.calc_text_index_for_width   =*/ simgraph16_calc_text_index_for_width,
 	/*.draw_text_clipped_n         =*/ simgraph16_draw_text_clipped_n,
 	/*.draw_multiline_text         =*/ simgraph16_draw_multiline_text,
 	/*.draw_text_ellipsis_shadowed =*/ simgraph16_draw_text_ellipsis_shadowed,
@@ -3654,199 +3630,12 @@ static void simgraph16_draw_array(scr_coord_val xp, scr_coord_val yp, scr_coord_
 
 // --------------------------------- text rendering stuff ------------------------------
 
-static bool simgraph16_load_font(const char *fname, bool reload)
-{
-	font_t loaded_fnt;
-
-	if(  fname == NULL  ) {
-		dbg->error( "display_load_font", "NULL filename" );
-		return false;
-	}
-
-	// skip reloading if already in memory, if bdf font
-	if(  !reload  &&  default_font.is_loaded()  &&  strcmp( default_font.get_fname(), fname ) == 0  ) {
-		return true;
-	}
-
-	if(  loaded_fnt.load_from_file(fname)  ) {
-		default_font = loaded_fnt;
-		default_font_ascent    = default_font.get_ascent();
-		default_font_linespace = default_font.get_linespace();
-
-		// find default number width
-		const char* digits = "0123456789";
-		default_font_numberwidth = 0;
-		while (*digits) {
-			int pixel = default_font.get_glyph_advance(*digits++);
-			if (pixel > default_font_numberwidth) {
-				default_font_numberwidth = pixel;
-			}
-		}
-
-		env_t::fontname = fname;
-
-		return default_font.is_loaded();
-	}
-
-	return false;
-}
-
-
-static scr_coord_val simgraph16_get_char_width(utf32 c)
-{
-	return default_font.get_glyph_advance(c);
-}
-
-
-static scr_coord_val simgraph16_get_number_width()
-{
-	return default_font_numberwidth;
-}
-
-/**
- * For the next logical character in the text, returns the character code
- * as well as retrieves the char byte count and the screen pixel width
- * CAUTION : The text pointer advances to point to the next logical character
- */
-static utf32 simgraph16_get_next_char_with_metrics(const char* &text, unsigned char &byte_length, unsigned char &pixel_width)
-{
-	size_t len = 0;
-	utf32 const char_code = utf8_decoder_t::decode((utf8 const *)text, len);
-
-	if(  char_code==UNICODE_NUL  ||  char_code == '\n') {
-		// case : end of text reached -> do not advance text pointer
-		// also stop at linebreaks
-		byte_length = 0;
-		pixel_width = 0;
-		return 0;
-	}
-	else {
-		text += len;
-		byte_length = (uint8)len;
-		pixel_width = default_font.get_glyph_advance(char_code);
-	}
-	return char_code;
-}
-
-
-/* returns true, if this is a valid character */
-static bool simgraph16_font_has_character(utf16 char_code)
-{
-	return default_font.is_valid_glyph(char_code);
-}
-
-
-
-/*
- * returns the index of the last character that would fit within the width
- * If an ellipsis len is given, it will only return the last character up to this len if the full length cannot be fitted
- * @returns index of next character. if text[index]==0 the whole string fits
- */
-static size_t simgraph16_calc_text_index_for_width(const char *text, scr_coord_val max_width)
-{
-	size_t max_idx = 0;
-
-	uint8 byte_length = 0;
-	uint8 pixel_width = 0;
-	scr_coord_val current_offset = 0;
-
-	const char *tmp_text = text;
-	while(  simgraph16_get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  max_width > (current_offset+pixel_width)  ) {
-		current_offset += pixel_width;
-		max_idx += byte_length;
-	}
-	return max_idx;
-}
-
-
-/**
- * For the previous logical character in the text, returns the character code
- * as well as retrieves the char byte count and the screen pixel width
- * CAUTION : The text pointer recedes to point to the previous logical character
- */
-static utf32 simgraph16_get_prev_char_with_metrics(const char* &text, const char *const text_start, unsigned char &byte_length, unsigned char &pixel_width)
-{
-	if(  text<=text_start  ) {
-		// case : start of text reached or passed -> do not move the pointer backwards
-		byte_length = 0;
-		pixel_width = 0;
-		return 0;
-	}
-
-	utf32 char_code;
-	// determine the start of the previous logical character
-	do {
-		--text;
-	} while (  text>text_start  &&  (*text & 0xC0)==0x80  );
-
-	size_t len = 0;
-	char_code = utf8_decoder_t::decode((utf8 const *)text, len);
-	byte_length = (uint8)len;
-	pixel_width = default_font.get_glyph_advance(char_code);
-
-	return char_code;
-}
-
-
-/* proportional_string_width with a text of a given length
-* extended for universal font routines with unicode support
-*/
-static scr_coord_val simgraph16_calc_text_width_n(const char *text, size_t len)
-{
-	uint8 byte_length = 0;
-	uint8 pixel_width = 0;
-	size_t idx = 0;
-	scr_coord_val width = 0;
-
-	while (simgraph16_get_next_char_with_metrics(text, byte_length, pixel_width)  &&  idx < len) {
-		width += pixel_width;
-		idx += byte_length;
-	}
-	return width;
-}
-
-
-/* display_calc_proportional_multiline_string_len_width
-* calculates the width and hieght of a box containing the text inside
-*/
-static scr_size simgraph16_calc_multiline_text_size(const char *text)
-{
-	const font_t* const fnt = &default_font;
-	int width = 0;
-	bool last_cr = false;
-
-	scr_size size{0,0};
-
-	const utf8 *p = reinterpret_cast<const utf8 *>(text);
-	while (const utf32 iUnicode = utf8_decoder_t::decode(p)) {
-
-		if(  iUnicode == '\n'  ) {
-			// new line: record max width
-			size.w = max( size.w, width );
-			size.h += LINESPACE;
-			width = 0;
-			last_cr = true;
-			continue;
-		}
-		last_cr = false;
-		width += fnt->get_glyph_advance(iUnicode);
-	}
-
-	size.w = max( size.w, width );
-	if (!last_cr) {
-		// extra CR of the last was not already a CR
-		size.h += LINESPACE;
-	}
-
-	return size;
-}
-
 
 /**
  * len parameter added - use -1 for previous behaviour.
  * completely renovated for unicode and 10 bit width and variable height
  */
-static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_val y, const char* txt, control_alignment_t flags, const PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF)
+static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_val y, const char *txt, const font_t *font, control_alignment_t flags, const PIXVAL color, bool dirty, sint32 len  CLIP_NUM_DEF)
 {
 	scr_coord_val cL, cR, cT, cB;
 
@@ -3876,18 +3665,15 @@ static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_v
 			break;
 
 		case ALIGN_CENTER_H:
-			x -= simgraph16_calc_text_width_n(txt, len) / 2;
+			x -= font->calc_text_width_n(txt, len) / 2;
 			break;
 
 		case ALIGN_RIGHT:
-			x -= simgraph16_calc_text_width_n(txt, len);
+			x -= font->calc_text_width_n(txt, len);
 			break;
 	}
 
-	// still something to display?
-	const font_t *const fnt = &default_font;
-
-	if (x >= cR || y >= cB || y + fnt->get_linespace() <= cT) {
+	if (x >= cR || y >= cB || y + font->get_linespace() <= cT) {
 		// nothing to display
 		return 0;
 	}
@@ -3909,12 +3695,12 @@ static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_v
 			break;
 		}
 		// print unknown character?
-		else if(  !fnt->is_valid_glyph(c)  ) {
+		else if(  !font->has_glyph_for_character(c)  ) {
 			c = 0;
 		}
 
 		// get the data from the font
-		const font_t::glyph_t& glyph = fnt->get_glyph(c);
+		const font_t::glyph_t& glyph = font->get_glyph(c);
 		const uint8 *p = glyph.bitmap;
 
 		int screen_pos = (y + glyph.top) * disp_width + x + glyph.left;
@@ -3947,12 +3733,12 @@ static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_v
 			screen_pos += disp_width;
 		}
 
-		x += fnt->get_glyph_advance(c);
+		x += font->get_glyph_advance(c);
 	}
 
 	if(  dirty  ) {
 		// here, because only now we know the length also for ALIGN_LEFT text
-		simgraph16_mark_rect_dirty_clip( x0, y, x - 1, y + LINESPACE - 1  CLIP_NUM_PAR);
+		simgraph16_mark_rect_dirty_clip( x0, y, x - 1, y + font->get_linespace() - 1  CLIP_NUM_PAR);
 	}
 
 	// warning: actual len might be longer, due to clipping!
@@ -3962,23 +3748,23 @@ static scr_coord_val simgraph16_draw_text_clipped_n(scr_coord_val x, scr_coord_v
 
 /// Displays a string which is abbreviated by the (language specific) ellipsis character if too wide
 /// If enough space is given then it just displays the full string
-static void simgraph16_draw_text_ellipsis_shadowed(scr_rect r, const char *text, int align, const PIXVAL color, const bool dirty, bool shadowed, PIXVAL shadow_color)
+static void simgraph16_draw_text_ellipsis_shadowed(scr_rect r, const char *text, const font_t *font, int align, const PIXVAL color, const bool dirty, bool shadowed, PIXVAL shadow_color)
 {
 	const scr_coord_val ellipsis_width = translator::get_lang()->ellipsis_width;
 	const scr_coord_val max_screen_width = r.w;
 	size_t max_idx = 0;
 
 	uint8 byte_length = 0;
-	uint8 pixel_width = 0;
+	scr_coord_val pixel_width = 0;
 	scr_coord_val current_offset = 0;
 
 	if(  align & ALIGN_CENTER_V  ) {
-		r.y += (r.h - LINESPACE)/2;
+		r.y += (r.h - font->get_linespace())/2;
 		align &= ~ALIGN_CENTER_V;
 	}
 
 	const char *tmp_text = text;
-	while(  simgraph16_get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  max_screen_width >= (current_offset+ellipsis_width+pixel_width)  ) {
+	while(  font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  max_screen_width >= (current_offset+ellipsis_width+pixel_width)  ) {
 		current_offset += pixel_width;
 		max_idx += byte_length;
 	}
@@ -3991,7 +3777,7 @@ static void simgraph16_draw_text_ellipsis_shadowed(scr_rect r, const char *text,
 		current_offset += pixel_width;
 		max_idx += byte_length;
 		// check the rest ...
-		while(  simgraph16_get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  max_screen_width >= (current_offset+pixel_width)  ) {
+		while(  font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  max_screen_width >= (current_offset+pixel_width)  ) {
 			current_offset += pixel_width;
 			max_idx += byte_length;
 		}
@@ -4003,15 +3789,15 @@ static void simgraph16_draw_text_ellipsis_shadowed(scr_rect r, const char *text,
 				w = (max_screen_width-max_offset_before_ellipsis-ellipsis_width)/2;
 			}
 			if (shadowed) {
-				simgraph16_draw_text_clipped_n( r.x+w+1, r.y+1, text, ALIGN_LEFT | DT_CLIP, shadow_color, dirty, max_idx_before_ellipsis  CLIP_NUM_DEFAULT);
+				simgraph16_draw_text_clipped_n( r.x+w+1, r.y+1, text, font, ALIGN_LEFT | DT_CLIP, shadow_color, dirty, max_idx_before_ellipsis  CLIP_NUM_DEFAULT);
 			}
-			w += simgraph16_draw_text_clipped_n( r.x+w, r.y, text, ALIGN_LEFT | DT_CLIP, color, dirty, max_idx_before_ellipsis  CLIP_NUM_DEFAULT);
+			w += simgraph16_draw_text_clipped_n( r.x+w, r.y, text, font, ALIGN_LEFT | DT_CLIP, color, dirty, max_idx_before_ellipsis  CLIP_NUM_DEFAULT);
 
 			if (shadowed) {
-				simgraph16_draw_text_clipped_n( r.x+w+1, r.y+1, translator::translate("..."), ALIGN_LEFT | DT_CLIP, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
+				simgraph16_draw_text_clipped_n( r.x+w+1, r.y+1, translator::translate("..."), font, ALIGN_LEFT | DT_CLIP, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
 			}
 
-			simgraph16_draw_text_clipped_n( r.x+w, r.y, translator::translate("..."), ALIGN_LEFT | DT_CLIP, color, dirty, -1  CLIP_NUM_DEFAULT);
+			simgraph16_draw_text_clipped_n( r.x+w, r.y, translator::translate("..."), font, ALIGN_LEFT | DT_CLIP, color, dirty, -1  CLIP_NUM_DEFAULT);
 			return;
 		}
 		else {
@@ -4029,9 +3815,9 @@ static void simgraph16_draw_text_ellipsis_shadowed(scr_rect r, const char *text,
 		default: ;
 	}
 	if (shadowed) {
-		simgraph16_draw_text_clipped_n( r.x+1, r.y+1, text, ALIGN_LEFT | DT_CLIP, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
+		simgraph16_draw_text_clipped_n( r.x+1, r.y+1, text, font, ALIGN_LEFT | DT_CLIP, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
 	}
-	simgraph16_draw_text_clipped_n( r.x, r.y, text, ALIGN_LEFT | DT_CLIP, color, dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n( r.x, r.y, text, font, ALIGN_LEFT | DT_CLIP, color, dirty, -1  CLIP_NUM_DEFAULT);
 }
 
 
@@ -4050,20 +3836,20 @@ static void simgraph16_draw_box3d(scr_coord_val x1, scr_coord_val y1, scr_coord_
 }
 
 
-static void simgraph16_draw_text_outlined(scr_coord_val xpos, scr_coord_val ypos, PIXVAL text_color, PIXVAL shadow_color, const char *text, int dirty)
+static void simgraph16_draw_text_outlined(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, PIXVAL text_color, PIXVAL shadow_color,  int dirty)
 {
 	const int flags = ALIGN_LEFT | DT_CLIP;
-	simgraph16_draw_text_clipped_n(xpos - 1, ypos    , text, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
-	simgraph16_draw_text_clipped_n(xpos + 1, ypos + 2, text, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
-	simgraph16_draw_text_clipped_n(xpos,     ypos + 1, text, flags, text_color,   dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n(xpos - 1, ypos    , text, font, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n(xpos + 1, ypos + 2, text, font, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n(xpos,     ypos + 1, text, font, flags, text_color,   dirty, -1  CLIP_NUM_DEFAULT);
 }
 
 
-static void simgraph16_draw_text_shadowed(scr_coord_val xpos, scr_coord_val ypos, PIXVAL text_color, PIXVAL shadow_color, const char *text, int dirty)
+static void simgraph16_draw_text_shadowed(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, PIXVAL text_color, PIXVAL shadow_color, int dirty)
 {
 	const int flags = ALIGN_LEFT | DT_CLIP;
-	simgraph16_draw_text_clipped_n(xpos + 1, ypos + 1 + (12 - LINESPACE) / 2, text, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
-	simgraph16_draw_text_clipped_n(xpos,     ypos +     (12 - LINESPACE) / 2, text, flags, text_color,   dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n(xpos + 1, ypos + 1 + (12 - font->get_linespace()) / 2, text, font, flags, shadow_color, dirty, -1  CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n(xpos,     ypos +     (12 - font->get_linespace()) / 2, text, font, flags, text_color,   dirty, -1  CLIP_NUM_DEFAULT);
 }
 
 
@@ -4085,33 +3871,37 @@ static void simgraph16_draw_box3d_clipped(scr_coord_val x1, scr_coord_val y1, sc
 /**
  * display text in 3d box with clipping
  */
-static void simgraph16_draw_textbox3d_clipped(scr_coord_val xpos, scr_coord_val ypos, FLAGGED_PIXVAL ddd_color, FLAGGED_PIXVAL text_color, const char *text, int dirty  CLIP_NUM_DEF)
+static void simgraph16_draw_textbox3d_clipped(scr_coord_val xpos, scr_coord_val ypos, const char *text, const font_t *font, FLAGGED_PIXVAL ddd_color, FLAGGED_PIXVAL text_color, int dirty  CLIP_NUM_DEF)
 {
-	const int vpadding = LINESPACE / 7;
-	const int hpadding = LINESPACE / 4;
+	const sint16 linespace = font->get_linespace();
+
+	const int vpadding = linespace / 7;
+	const int hpadding = linespace / 4;
 
-	scr_coord_val width = simgraph16_calc_text_width_n(text, 0x7FFFu);
+	scr_coord_val width = font->calc_text_width_n(text, 0x7FFFu);
 
 	PIXVAL lighter = display_blend_colors_alpha32(ddd_color, gfx->palette_lookup(COL_WHITE), 8 /* 25% */);
 	PIXVAL darker  = display_blend_colors_alpha32(ddd_color, gfx->palette_lookup(COL_BLACK), 8 /* 25% */);
 
-	simgraph16_draw_rect_clipped( xpos+1, ypos - vpadding + 1, width+2*hpadding-2, LINESPACE+2*vpadding-1, ddd_color, dirty CLIP_NUM_PAR);
+	simgraph16_draw_rect_clipped( xpos+1, ypos - vpadding + 1, width+2*hpadding-2, linespace+2*vpadding-1, ddd_color, dirty CLIP_NUM_PAR);
 
 	gfx->draw_rect_clipped( xpos, ypos - vpadding,             width + 2*hpadding - 2, 1, lighter, dirty CLIP_NUM_DEFAULT);
-	gfx->draw_rect_clipped( xpos, ypos + LINESPACE + vpadding, width + 2*hpadding - 2, 1, darker,  dirty CLIP_NUM_DEFAULT);
+	gfx->draw_rect_clipped( xpos, ypos + linespace + vpadding, width + 2*hpadding - 2, 1, darker,  dirty CLIP_NUM_DEFAULT);
 
-	simgraph16_draw_vline_clipped( xpos,                          ypos - vpadding, LINESPACE + vpadding * 2, lighter, dirty CLIP_NUM_DEFAULT);
-	simgraph16_draw_vline_clipped( xpos + width + 2*hpadding - 2, ypos - vpadding, LINESPACE + vpadding * 2, darker,  dirty CLIP_NUM_DEFAULT);
+	simgraph16_draw_vline_clipped( xpos,                          ypos - vpadding, linespace + vpadding * 2, lighter, dirty CLIP_NUM_DEFAULT);
+	simgraph16_draw_vline_clipped( xpos + width + 2*hpadding - 2, ypos - vpadding, linespace + vpadding * 2, darker,  dirty CLIP_NUM_DEFAULT);
 
-	simgraph16_draw_text_clipped_n( xpos+hpadding, ypos+1, text, ALIGN_LEFT | DT_CLIP, text_color, dirty, -1 CLIP_NUM_DEFAULT);
+	simgraph16_draw_text_clipped_n( xpos+hpadding, ypos+1, text, font, ALIGN_LEFT | DT_CLIP, text_color, dirty, -1 CLIP_NUM_DEFAULT);
 }
 
 
 /**
  * Draw multiline text
  */
-static scr_coord_val simgraph16_draw_multiline_text(scr_coord_val x, scr_coord_val y, const char *buf, PIXVAL color)
+static scr_coord_val simgraph16_draw_multiline_text(scr_coord_val x, scr_coord_val y, const char *buf, const font_t *font, PIXVAL color)
 {
+	const sint16 linespace = font->get_linespace();
+
 	scr_coord_val max_px_len = 0;
 	if (buf != NULL && *buf != '\0') {
 		const char *next;
@@ -4120,6 +3910,7 @@ static scr_coord_val simgraph16_draw_multiline_text(scr_coord_val x, scr_coord_v
 			next = strchr(buf, '\n');
 			const scr_coord_val px_len = simgraph16_draw_text_clipped_n(
 				x, y, buf,
+				font,
 				ALIGN_LEFT | DT_CLIP, color, true,
 				next != NULL ? (int)(size_t)(next - buf) : -1
 				CLIP_NUM_DEFAULT
@@ -4127,7 +3918,7 @@ static scr_coord_val simgraph16_draw_multiline_text(scr_coord_val x, scr_coord_v
 			if(  px_len>max_px_len  ) {
 				max_px_len = px_len;
 			}
-			y += LINESPACE;
+			y += linespace;
 		} while ((void)(buf = (next ? next+1 : NULL)), buf != NULL);
 	}
 	return max_px_len;
@@ -4677,18 +4468,6 @@ static bool simgraph16_init(scr_size window_size, sint16 full_screen)
 
 	textur = dr_textur_init();
 
-	// init, load, and check fonts
-	if (!gfx->load_font(env_t::fontname.c_str(), false)) {
-		env_t::fontname = dr_get_system_font();
-		if (!gfx->load_font(env_t::fontname.c_str(), false)) {
-			env_t::fontname = FONT_PATH_X "cyr.bdf";
-			if (!gfx->load_font(env_t::fontname.c_str(), false)) {
-				dr_fatal_notify("No fonts found!");
-				return false;
-			}
-		}
-	}
-
 	// allocate dirty tile flags
 	tiles_per_line = (disp_width + DIRTY_TILE_SIZE - 1) / DIRTY_TILE_SIZE;
 	tile_buffer_per_line = (tiles_per_line + 31) & ~31;
@@ -4744,7 +4523,7 @@ static bool simgraph16_init(scr_size window_size, sint16 full_screen)
  */
 static bool simgraph16_is_display_init()
 {
-	return textur != NULL  &&  default_font.is_loaded()  &&  images!=NULL;
+	return textur != NULL  &&  images!=NULL;
 }
 
 
diff --git a/src/simutrans/ground/grund.cc b/src/simutrans/ground/grund.cc
index ac11a81bf..7e03751c0 100644
--- a/src/simutrans/ground/grund.cc
+++ b/src/simutrans/ground/grund.cc
@@ -13,6 +13,7 @@
 #include "../display/viewport.h"
 #include "../simhalt.h"
 #include "../display/simimg.h"
+#include "../display/font.h"
 #include "../player/simplay.h"
 #include "../gui/simwin.h"
 #include "../world/simworld.h"
@@ -1681,12 +1682,12 @@ void display_text_label(sint16 xpos, sint16 ypos, const char* text, const player
 	switch( env_t::show_names >> 2 ) {
 		case 0: {
 			const PIXVAL bg_color = player ? gfx->palette_lookup(player->get_player_color1()+4) : SYSCOL_TEXT_HIGHLIGHT;
-			gfx->draw_textbox3d_clipped( xpos, ypos, bg_color, gfx->palette_lookup(COL_BLACK), text, dirty CLIP_NUM_DEFAULT);
+			gfx->draw_textbox3d_clipped( xpos, ypos, text, font_t::default_font, bg_color, gfx->palette_lookup(COL_BLACK), dirty CLIP_NUM_DEFAULT);
 			break;
 		}
 		case 1: {
 			const PIXVAL text_color = player ? gfx->palette_lookup(player->get_player_color1()+7) : SYSCOL_TEXT_HIGHLIGHT;
-			gfx->draw_text_outlined(xpos, ypos, text_color, gfx->palette_lookup(COL_BLACK), text, dirty);
+			gfx->draw_text_outlined(xpos, ypos, text, font_t::default_font, text_color, gfx->palette_lookup(COL_BLACK), dirty);
 			break;
 		}
 		case 2: {
@@ -1694,7 +1695,7 @@ void display_text_label(sint16 xpos, sint16 ypos, const char* text, const player
 			const PIXVAL normal = player ? gfx->palette_lookup(player->get_player_color1()+4) : SYSCOL_TEXT_HIGHLIGHT;
 			const PIXVAL bright = player ? gfx->palette_lookup(player->get_player_color1()+6) : SYSCOL_TEXT_HIGHLIGHT;
 
-			gfx->draw_text_outlined( xpos + LINESPACE + D_H_SPACE, ypos,   gfx->palette_lookup(COL_YELLOW), gfx->palette_lookup(COL_BLACK), text, dirty );
+			gfx->draw_text_outlined( xpos + LINESPACE + D_H_SPACE, ypos,   text, font_t::default_font, gfx->palette_lookup(COL_YELLOW), gfx->palette_lookup(COL_BLACK), dirty );
 			gfx->draw_box3d_clipped( xpos,                         ypos,   LINESPACE,   LINESPACE,   dark, PLAYER_FLAG|bright );
 			gfx->draw_rect(          xpos+1,                       ypos+1, LINESPACE-2, LINESPACE-2, normal, dirty );
 			break;
@@ -1714,7 +1715,7 @@ void grund_t::display_overlay(const sint16 xpos, const sint16 ypos)
 		if(  env_t::show_names & 1  ) {
 			const char *text = get_text();
 			const sint16 raster_tile_width = gfx->get_tile_raster_width();
-			const int width = gfx->calc_text_width(text) + 7;
+			const int width = font_t::default_font->calc_text_width(text) + 7;
 			int new_xpos = xpos - (width-raster_tile_width)/2;
 
 			const player_t* owner = get_label_owner();
@@ -1737,7 +1738,7 @@ void grund_t::display_overlay(const sint16 xpos, const sint16 ypos)
 				if( env_t::show_factory_storage_bar == 1  &&  welt->get_zeiger()->get_pos() == get_pos() ) {
 					const sint16 raster_tile_width = gfx->get_tile_raster_width();
 					const char* text = fab->get_name();
-					const int width = gfx->calc_text_width(text) + 7;
+					const int width = font_t::default_font->calc_text_width(text) + 7;
 					sint16 new_xpos = xpos - (width-raster_tile_width)/2;
 					sint16 new_ypos = ypos + 5;
 //					display_text_label( new_xpos, new_ypos, text, fab->get_owner(), dirty );
@@ -1750,7 +1751,7 @@ void grund_t::display_overlay(const sint16 xpos, const sint16 ypos)
 						// name of factory
 						const char* text = fab->get_name();
 						const sint16 raster_tile_width = gfx->get_tile_raster_width();
-						const sint16 width = gfx->calc_text_width(text) + 7;
+						const sint16 width = font_t::default_font->calc_text_width(text) + 7;
 						sint16 new_xpos = xpos - (width-raster_tile_width)/2;
 						display_text_label( new_xpos, ypos, text, fab->get_owner(), dirty );
 						// ... and status
diff --git a/src/simutrans/gui/banner.cc b/src/simutrans/gui/banner.cc
index 073c53930..19103987a 100644
--- a/src/simutrans/gui/banner.cc
+++ b/src/simutrans/gui/banner.cc
@@ -11,6 +11,7 @@
 #include "../sys/simsys.h"
 #include "../simversion.h"
 #include "../display/simgraph.h"
+#include "../display/font.h"
 #include "../macros.h"
 #include "../descriptor/skin_desc.h"
 #include "../dataobj/environment.h"
@@ -307,8 +308,8 @@ void banner_text_t::draw(scr_coord offset)
 			color = gfx->palette_lookup(colors[0]);
 		}
 
-		gfx->draw_text_clipped( left +         L_BANNER_TEXT_INDENT, cursor.y - text_offset, scrolltext[text_line + row*2    ], ALIGN_LEFT,  color, false);
-		gfx->draw_text_clipped( left + width - L_BANNER_TEXT_INDENT, cursor.y - text_offset, scrolltext[text_line + row*2 + 1], ALIGN_RIGHT, color, false);
+		gfx->draw_text_clipped( left +         L_BANNER_TEXT_INDENT, cursor.y - text_offset, scrolltext[text_line + row*2    ], font_t::default_font, ALIGN_LEFT,  color, false);
+		gfx->draw_text_clipped( left + width - L_BANNER_TEXT_INDENT, cursor.y - text_offset, scrolltext[text_line + row*2 + 1], font_t::default_font, ALIGN_RIGHT, color, false);
 
 		cursor.y += LINESPACE;
 	}
diff --git a/src/simutrans/gui/chat_frame.cc b/src/simutrans/gui/chat_frame.cc
index 010c72fed..7bc36999b 100644
--- a/src/simutrans/gui/chat_frame.cc
+++ b/src/simutrans/gui/chat_frame.cc
@@ -16,6 +16,7 @@
 #include "../network/network_cmd_ingame.h"
 #include "../player/simplay.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 #include "../gui/messagebox.h"
 
 
diff --git a/src/simutrans/gui/city_info.cc b/src/simutrans/gui/city_info.cc
index 7d56df390..cc590c804 100644
--- a/src/simutrans/gui/city_info.cc
+++ b/src/simutrans/gui/city_info.cc
@@ -11,6 +11,7 @@
 #include "../dataobj/environment.h"
 #include "../dataobj/translator.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 #include "../utils/cbuffer.h"
 #include "../utils/simstring.h"
 #include "../tpl/array2d_tpl.h"
diff --git a/src/simutrans/gui/citylist_frame.cc b/src/simutrans/gui/citylist_frame.cc
index 7e7177449..3437a4eba 100644
--- a/src/simutrans/gui/citylist_frame.cc
+++ b/src/simutrans/gui/citylist_frame.cc
@@ -8,10 +8,11 @@
 
 
 #include "../player/simplay.h"
+#include "../dataobj/environment.h"
 #include "../dataobj/translator.h"
+#include "../display/font.h"
 #include "../simcolor.h"
 #include "../simhalt.h"
-#include "../dataobj/environment.h"
 #include "../utils/cbuffer.h"
 #include "../utils/unicode.h"
 #include "components/gui_button_to_chart.h"
diff --git a/src/simutrans/gui/components/gui_button.cc b/src/simutrans/gui/components/gui_button.cc
index 8328f5466..1bc4ef7a3 100644
--- a/src/simutrans/gui/components/gui_button.cc
+++ b/src/simutrans/gui/components/gui_button.cc
@@ -26,6 +26,7 @@
 #include "../../world/simworld.h"
 #include "../../ground/grund.h"
 #include "../../display/viewport.h"
+#include "../../display/font.h"
 #include "../../obj/zeiger.h"
 
 #include "../gui_frame.h"
@@ -80,7 +81,7 @@ void button_t::set_typ(enum type t)
 			text_color = SYSCOL_CHECKBOX_TEXT;
 			if(  !strempty(translated_text)  ) {
 				set_text(translated_text);
-				set_size( scr_size( gui_theme_t::gui_checkbox_size.w + D_H_SPACE + gfx->calc_text_width(translated_text), max(gui_theme_t::gui_checkbox_size.h,LINESPACE)) );
+				set_size( scr_size( gui_theme_t::gui_checkbox_size.w + D_H_SPACE + font_t::default_font->calc_text_width(translated_text), max(gui_theme_t::gui_checkbox_size.h,LINESPACE)) );
 			}
 			else {
 				set_size( scr_size( gui_theme_t::gui_checkbox_size.w, max(gui_theme_t::gui_checkbox_size.h,LINESPACE)) );
@@ -180,12 +181,12 @@ scr_size button_t::get_min_size() const
 			return gui_theme_t::gui_arrow_down_size;
 
 		case square: {
-			scr_coord_val w = translated_text ?  D_H_SPACE + gfx->calc_text_width( translated_text ) : 0;
+			scr_coord_val w = translated_text ?  D_H_SPACE + font_t::default_font->calc_text_width( translated_text ) : 0;
 			return scr_size(w + gui_theme_t::gui_checkbox_size.w, max(gui_theme_t::gui_checkbox_size.h,LINESPACE));
 		}
 		case box:
 		case roundbox: {
-			scr_coord_val w = translated_text ?  2*D_H_SPACE + gfx->calc_text_width( translated_text ) : 0;
+			scr_coord_val w = translated_text ?  2*D_H_SPACE + font_t::default_font->calc_text_width( translated_text ) : 0;
 			scr_size size(gui_theme_t::gui_button_size.w, max(D_BUTTON_HEIGHT,LINESPACE));
 			size.w = max(size.w, w);
 			return size;
@@ -220,7 +221,7 @@ void button_t::set_text(const char * text)
 	translated_text = b_no_translate ? text : translator::translate(text);
 
 	if(  (type & TYPE_MASK) == square  &&  !strempty(translated_text)  ) {
-		set_size( scr_size( gui_theme_t::gui_checkbox_size.w + D_H_SPACE + gfx->calc_text_width( translated_text ), max(gui_theme_t::gui_checkbox_size.h, LINESPACE)) );
+		set_size( scr_size( gui_theme_t::gui_checkbox_size.w + D_H_SPACE + font_t::default_font->calc_text_width( translated_text ), max(gui_theme_t::gui_checkbox_size.h, LINESPACE)) );
 	}
 }
 
@@ -361,7 +362,7 @@ void button_t::draw(scr_coord offset)
 					// move the text to leave evt. space for a colored box top left or bottom right of it
 					scr_rect area_text = area - gui_theme_t::gui_color_button_text_offset_right;
 					area_text.set_pos( gui_theme_t::gui_color_button_text_offset + area.get_pos() );
-					gfx->draw_text_ellipsis( area_text, translated_text, ALIGN_CENTER_H | ALIGN_CENTER_V | DT_CLIP, text_color, true );
+					gfx->draw_text_ellipsis( area_text, translated_text, font_t::default_font, ALIGN_CENTER_H | ALIGN_CENTER_V | DT_CLIP, text_color, true );
 				}
 				if(  win_get_focus()==this  ) {
 					draw_focus_rect( area );
@@ -376,7 +377,7 @@ void button_t::draw(scr_coord offset)
 					// move the text to leave evt. space for a colored box top left or bottom right of it
 					scr_rect area_text = area - gui_theme_t::gui_button_text_offset_right;
 					area_text.set_pos( gui_theme_t::gui_button_text_offset + area.get_pos() );
-					gfx->draw_text_ellipsis( area_text, translated_text, ALIGN_CENTER_H | ALIGN_CENTER_V | DT_CLIP, text_color, true );
+					gfx->draw_text_ellipsis( area_text, translated_text, font_t::default_font, ALIGN_CENTER_H | ALIGN_CENTER_V | DT_CLIP, text_color, true );
 				}
 				if(  win_get_focus()==this  ) {
 					draw_focus_rect( area );
@@ -437,7 +438,7 @@ void button_t::draw(scr_coord offset)
 					scr_rect area_text = area;
 					area_text.x += gui_theme_t::gui_checkbox_size.w + D_H_SPACE;
 					area_text.w -= gui_theme_t::gui_checkbox_size.w + D_H_SPACE;
-					gfx->draw_text_ellipsis( area_text, translated_text, ALIGN_LEFT | ALIGN_CENTER_V | DT_CLIP, text_color, true );
+					gfx->draw_text_ellipsis( area_text, translated_text, font_t::default_font, ALIGN_LEFT | ALIGN_CENTER_V | DT_CLIP, text_color, true );
 				}
 				if(  win_get_focus() == this  ) {
 					draw_focus_rect( scr_rect( area.get_pos()+scr_coord(0,(area.get_size().h-gui_theme_t::gui_checkbox_size.w)/2), gui_theme_t::gui_checkbox_size ) );
diff --git a/src/simutrans/gui/components/gui_chart.cc b/src/simutrans/gui/components/gui_chart.cc
index 7f3a68a8f..f26764e0e 100644
--- a/src/simutrans/gui/components/gui_chart.cc
+++ b/src/simutrans/gui/components/gui_chart.cc
@@ -13,6 +13,8 @@
 #include "../../utils/simstring.h"
 #include "../../dataobj/environment.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
+
 #include "../gui_theme.h"
 
 static char tooltip[64];
@@ -143,12 +145,12 @@ void gui_chart_t::draw(scr_coord offset)
 
 		// draw zero number only, if it will not disturb any other printed values!
 		if ((baseline > 18) && (baseline < chart_size.h -18)) {
-			gfx->draw_text_clipped(offset.x - 4, offset.y+(scr_coord_val)baseline-3, "0", ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
+			gfx->draw_text_clipped(offset.x - 4, offset.y+(scr_coord_val)baseline-3, "0", font_t::default_font, ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
 		}
 
 		// display min/max money values
-		gfx->draw_text_clipped(offset.x - 4, offset.y-5,              cmax, ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
-		gfx->draw_text_clipped(offset.x - 4, offset.y+chart_size.h-5, cmin, ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
+		gfx->draw_text_clipped(offset.x - 4, offset.y-5,              cmax, font_t::default_font, ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
+		gfx->draw_text_clipped(offset.x - 4, offset.y+chart_size.h-5, cmin, font_t::default_font, ALIGN_RIGHT, SYSCOL_TEXT_HIGHLIGHT, true );
 	}
 
 	// draw chart frame
@@ -165,7 +167,7 @@ void gui_chart_t::draw(scr_coord offset)
 			sprintf( digit, "%i", abs(seed - j) );
 			scr_coord_val x =  x0 - (seed != j ? (int)(2 * log( (double)abs(seed - j) )) : 0);
 			if(  x > x_last  ) {
-				x_last = x + gfx->draw_text_clipped( x, offset.y + chart_size.h + 4, digit, ALIGN_LEFT, line_color, true );
+				x_last = x + gfx->draw_text_clipped( x, offset.y + chart_size.h + 4, digit, font_t::default_font, ALIGN_LEFT, line_color, true );
 			}
 		}
 		// year's vertical lines
@@ -235,10 +237,10 @@ void gui_chart_t::draw(scr_coord offset)
 						}
 
 						if(  env_t::left_to_right_graphs  ) {
-							gfx->draw_textbox3d_clipped( tmpx + 8, (scr_coord_val)(offset.y+baseline-(int)(tmp/scale)-4), gfx->palette_lookup(COL_GREY4), c.color, cmin, true CLIP_NUM_DEFAULT);
+							gfx->draw_textbox3d_clipped( tmpx + 8, (scr_coord_val)(offset.y+baseline-(int)(tmp/scale)-4), cmin, font_t::default_font, gfx->palette_lookup(COL_GREY4), c.color, true CLIP_NUM_DEFAULT);
 						}
 						else if(  (baseline-tmp/scale-8) > 0  &&  (baseline-tmp/scale+8) < chart_size.h  &&  abs((int)(tmp/scale)) > 9  ) {
-							gfx->draw_text_clipped(tmpx - 4, (scr_coord_val)(offset.y+baseline-(int)(tmp/scale)-4), cmin, ALIGN_RIGHT, c.color, true );
+							gfx->draw_text_clipped(tmpx - 4, (scr_coord_val)(offset.y+baseline-(int)(tmp/scale)-4), cmin, font_t::default_font, ALIGN_RIGHT, c.color, true );
 						}
 					}
 				}
diff --git a/src/simutrans/gui/components/gui_combobox.cc b/src/simutrans/gui/components/gui_combobox.cc
index 24181f248..08ea85b81 100644
--- a/src/simutrans/gui/components/gui_combobox.cc
+++ b/src/simutrans/gui/components/gui_combobox.cc
@@ -15,6 +15,7 @@
 #include "gui_combobox.h"
 #include "../../simevent.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../display/scr_coord.h"
 #include "../../simcolor.h"
 #include "../simwin.h"
diff --git a/src/simutrans/gui/components/gui_fixedwidth_textarea.cc b/src/simutrans/gui/components/gui_fixedwidth_textarea.cc
index d0d695503..1f30df819 100644
--- a/src/simutrans/gui/components/gui_fixedwidth_textarea.cc
+++ b/src/simutrans/gui/components/gui_fixedwidth_textarea.cc
@@ -8,6 +8,7 @@
 #include "../gui_theme.h"
 #include "gui_fixedwidth_textarea.h"
 #include "../../dataobj/translator.h"
+#include "../../display/font.h"
 #include "../../utils/cbuffer.h"
 #include "../../utils/unicode.h"
 
@@ -111,7 +112,7 @@ scr_size gui_fixedwidth_textarea_t::calc_display_text(const scr_coord offset, co
 
 			const size_t len = next ? next - buf : 999;
 			// we are in the image area
-			scr_coord_val px_len = gfx->calc_text_width_n(buf, len);
+			scr_coord_val px_len = font_t::default_font->calc_text_width_n(buf, len);
 			if (new_height <= reserved_area.h) {
 				px_len += reserved_area.w;
 			}
@@ -157,14 +158,14 @@ scr_size gui_fixedwidth_textarea_t::calc_display_text(const scr_coord offset, co
 			else if(  next_char==' '  ||  (next_char >= 0x3000  &&   next_char<0xFE70)  ) {
 				// ignore space at start of line
 				if(next_char!=' '  ||  x>0) {
-					x += gfx->get_char_width( next_char );
+					x += font_t::default_font->get_char_width( next_char );
 				}
 				word_start = p;
 				word_x = 0;
 			}
 			else {
 				// normal char: retrieve and calculate width
-				const scr_coord_val ch_width = gfx->get_char_width( next_char );
+				const scr_coord_val ch_width = font_t::default_font->get_char_width( next_char );
 				x += ch_width;
 				word_x += ch_width;
 			}
@@ -183,7 +184,7 @@ scr_size gui_fixedwidth_textarea_t::calc_display_text(const scr_coord offset, co
 
 		// start of new line or end of text
 		if(draw  &&  (line_end-line_start)!=0) {
-			gfx->draw_text_clipped_n( offset.x, offset.y+y, (const char *)line_start, ALIGN_LEFT | DT_CLIP, SYSCOL_TEXT, true, (size_t)(line_end - line_start) CLIP_NUM_DEFAULT);
+			gfx->draw_text_clipped_n( offset.x, offset.y+y, (const char *)line_start, font_t::default_font, ALIGN_LEFT | DT_CLIP, SYSCOL_TEXT, true, (size_t)(line_end - line_start) CLIP_NUM_DEFAULT);
 		}
 		y += LINESPACE;
 		// back to start of new line
diff --git a/src/simutrans/gui/components/gui_flowtext.cc b/src/simutrans/gui/components/gui_flowtext.cc
index ec871b082..07949e0aa 100644
--- a/src/simutrans/gui/components/gui_flowtext.cc
+++ b/src/simutrans/gui/components/gui_flowtext.cc
@@ -12,6 +12,7 @@
 #include "../../descriptor/skin_desc.h"
 #include "../../display/simgraph.h"
 #include "../../display/simimg.h"
+#include "../../display/font.h"
 #include "../../utils/simstring.h"
 #include "../../utils/unicode.h"
 #include "../gui_theme.h"
@@ -437,13 +438,13 @@ scr_size gui_flowtext_intern_t::output(scr_coord offset, bool doit, bool return_
 	int last_link_x     = 0;     // at this position ye need to continue underline drawing
 	int max_width    = width;
 	int text_width   = width;
-	const int space_width = gfx->calc_text_width(" ");
+	const int space_width = font_t::default_font->calc_text_width(" ");
 
 	for(node_t const& i : nodes) {
 		switch (i.att) {
 			case ATT_NONE:
 			case ATT_NO_SPACE: {
-				int nxpos = xpos + gfx->calc_text_width(i.text.c_str());
+				int nxpos = xpos + font_t::default_font->calc_text_width(i.text.c_str());
 
 				if (nxpos >= text_width) {
 					text_width = nxpos;
@@ -490,10 +491,10 @@ scr_size gui_flowtext_intern_t::output(scr_coord offset, bool doit, bool return_
 
 				if (doit) {
 					if (double_it) {
-						gfx->draw_text_clipped(offset.x + xpos + 1 + D_MARGIN_LEFT, offset.y + ypos + 1, i.text.c_str(), 0, double_color, false);
+						gfx->draw_text_clipped(offset.x + xpos + 1 + D_MARGIN_LEFT, offset.y + ypos + 1, i.text.c_str(), font_t::default_font, 0, double_color, false);
 						extra_pixel |= 1;
 					}
-					scr_coord_val width = gfx->draw_text_clipped(offset.x + xpos + D_MARGIN_LEFT, offset.y + ypos, i.text.c_str(), 0, color, false);
+					scr_coord_val width = gfx->draw_text_clipped(offset.x + xpos + D_MARGIN_LEFT, offset.y + ypos, i.text.c_str(), font_t::default_font, 0, color, false);
 					if(  link_it  ) {
 						gfx->draw_rect_clipped( offset.x + last_link_x + D_MARGIN_LEFT, ypos + offset.y + LINESPACE-1, (xpos+width)-last_link_x, 1, color, false CLIP_NUM_DEFAULT);
 						last_link_x = xpos+width;
diff --git a/src/simutrans/gui/components/gui_image_list.cc b/src/simutrans/gui/components/gui_image_list.cc
index 58ee3e398..aa18c1e83 100644
--- a/src/simutrans/gui/components/gui_image_list.cc
+++ b/src/simutrans/gui/components/gui_image_list.cc
@@ -6,6 +6,7 @@
 #include "../../simdebug.h"
 #include "gui_image_list.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../simevent.h"
 #include "../../simcolor.h"
 
@@ -109,11 +110,11 @@ void gui_image_list_t::draw(scr_coord parent_pos)
 				// Let's make a black background to ensure visibility
 				for(int iy = -3; iy < 0; iy++) {
 					for(int ix = 1; ix < 4; ix++) {
-						gfx->draw_text_clipped(xpos + ix, ypos + iy, text, ALIGN_LEFT, gfx->palette_lookup(COL_BLACK), true);
+						gfx->draw_text_clipped(xpos + ix, ypos + iy, text, font_t::default_font, ALIGN_LEFT, gfx->palette_lookup(COL_BLACK), true);
 					}
 				}
 				// Display the number white on black
-				gfx->draw_text_clipped(xpos + 2, ypos - 2, text, ALIGN_LEFT, gfx->palette_lookup(COL_WHITE), true);
+				gfx->draw_text_clipped(xpos + 2, ypos - 2, text, font_t::default_font, ALIGN_LEFT, gfx->palette_lookup(COL_WHITE), true);
 			}
 		}
 		// advance x, y to next position
diff --git a/src/simutrans/gui/components/gui_label.cc b/src/simutrans/gui/components/gui_label.cc
index 99acf1211..0cfea56f6 100644
--- a/src/simutrans/gui/components/gui_label.cc
+++ b/src/simutrans/gui/components/gui_label.cc
@@ -6,6 +6,7 @@
 #include "gui_label.h"
 #include "../gui_frame.h"
 #include "../../dataobj/translator.h"
+#include "../../display/font.h"
 #include "../../utils/simstring.h"
 #include "../simwin.h"
 
@@ -19,12 +20,12 @@ static scr_coord_val large_money_width = 0;
 gui_label_t::gui_label_t(const char* text, PIXVAL color_, align_t align_) :
 	align(align_), tooltip(NULL)
 {
-	separator_width = gfx->calc_text_width( ",00$" );
+	separator_width = font_t::default_font->calc_text_width( ",00$" );
 
 	if (get_large_money_string()) {
 		cbuffer_t buf;
 		buf.printf("%s$", get_large_money_string());
-		large_money_width = gfx->calc_text_width((const char*) buf);
+		large_money_width = font_t::default_font->calc_text_width((const char*) buf);
 	}
 	else {
 		large_money_width = 0;
@@ -38,7 +39,7 @@ gui_label_t::gui_label_t(const char* text, PIXVAL color_, align_t align_) :
 
 scr_size gui_label_t::get_min_size() const
 {
-	return scr_size( text ? gfx->calc_text_width(text) : D_BUTTON_WIDTH, D_LABEL_HEIGHT );
+	return scr_size( text ? font_t::default_font->calc_text_width(text) : D_BUTTON_WIDTH, D_LABEL_HEIGHT );
 }
 
 scr_size gui_label_t::get_max_size() const
@@ -63,7 +64,7 @@ void gui_label_t::set_text_pointer(const char *text_par, bool autosize)
 	text = text_par;
 
 	if (autosize && text && *text != '\0') {
-		set_size( scr_size( gfx->calc_text_width(text), size.h ) );
+		set_size( scr_size( font_t::default_font->calc_text_width(text), size.h ) );
 	}
 }
 
@@ -98,20 +99,20 @@ void gui_label_t::draw(scr_coord offset)
 			}
 
 			if(separator) {
-				gfx->draw_text_clipped(right.x, right.y, separator, ALIGN_LEFT, color, true);
+				gfx->draw_text_clipped(right.x, right.y, separator, font_t::default_font, ALIGN_LEFT, color, true);
 				if(  separator!=text  ) {
 					if (shadowed) {
-						gfx->draw_text_clipped_n(right.x+1, right.y+1, text, ALIGN_RIGHT | DT_CLIP, color_shadow, true, separator - text CLIP_NUM_DEFAULT);
+						gfx->draw_text_clipped_n(right.x+1, right.y+1, text, font_t::default_font, ALIGN_RIGHT | DT_CLIP, color_shadow, true, separator - text CLIP_NUM_DEFAULT);
 					}
-					gfx->draw_text_clipped_n(right.x, right.y, text, ALIGN_RIGHT | DT_CLIP, color, true, separator-text CLIP_NUM_DEFAULT);
+					gfx->draw_text_clipped_n(right.x, right.y, text, font_t::default_font, ALIGN_RIGHT | DT_CLIP, color, true, separator-text CLIP_NUM_DEFAULT);
 				}
 			}
 			else {
 				// integer or normal text
 				if (shadowed) {
-					gfx->draw_text_clipped(right.x + 1, right.y + 1, text, ALIGN_RIGHT | DT_CLIP, color_shadow, true);
+					gfx->draw_text_clipped(right.x + 1, right.y + 1, text, font_t::default_font, ALIGN_RIGHT | DT_CLIP, color_shadow, true);
 				}
-				gfx->draw_text_clipped(right.x, right.y, text, ALIGN_RIGHT, color, true);
+				gfx->draw_text_clipped(right.x, right.y, text, font_t::default_font, ALIGN_RIGHT, color, true);
 			}
 		}
 	}
@@ -119,7 +120,7 @@ void gui_label_t::draw(scr_coord offset)
 	else if(text) {
 		const scr_rect area( offset+pos, size );
 		int a = align == left ? ALIGN_LEFT : ( align == right ? ALIGN_RIGHT : ALIGN_CENTER_H);
-		gfx->draw_text_ellipsis_shadowed( area, text,  a | DT_CLIP, color, true, shadowed, color_shadow );
+		gfx->draw_text_ellipsis_shadowed( area, text, font_t::default_font, a | DT_CLIP, color, true, shadowed, color_shadow );
 	}
 
 	if ( tooltip  &&  getroffen(get_mouse_pos() - offset) ) {
diff --git a/src/simutrans/gui/components/gui_numberinput.cc b/src/simutrans/gui/components/gui_numberinput.cc
index 671407282..24c619718 100644
--- a/src/simutrans/gui/components/gui_numberinput.cc
+++ b/src/simutrans/gui/components/gui_numberinput.cc
@@ -8,6 +8,7 @@
 #include "../gui_frame.h"
 #include "../simwin.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../macros.h"
 #include "../../dataobj/translator.h"
 
@@ -115,7 +116,7 @@ void gui_numberinput_t::set_limits(sint32 _min, sint32 _max)
 	max_value = _max;
 
 	// minus sign
-	max_numbertext_width = (min_value > 0) ? 0 : gfx->get_char_width('-');
+	max_numbertext_width = (min_value > 0) ? 0 : font_t::default_font->get_char_width('-');
 	// count digits
 	uint32 max_abs = max_value > 0 ? max_value : -max_value;
 	if (min_value < 0  &&  (uint32) (-min_value) > max_abs) {
@@ -123,12 +124,12 @@ void gui_numberinput_t::set_limits(sint32 _min, sint32 _max)
 	}
 	// width of digits
 	while (max_abs) {
-		max_numbertext_width += gfx->get_number_width();
+		max_numbertext_width += font_t::default_font->get_number_width();
 		max_abs /= 10;
 	}
 	// enforce a min width of 5 digits
-	if (max_numbertext_width < 5 * gfx->get_number_width()) {
-		max_numbertext_width = 5 * gfx->get_number_width();
+	if (max_numbertext_width < 5 * font_t::default_font->get_number_width()) {
+		max_numbertext_width = 5 * font_t::default_font->get_number_width();
 	}
 }
 
diff --git a/src/simutrans/gui/components/gui_schedule.cc b/src/simutrans/gui/components/gui_schedule.cc
index 75325641b..6d65e6d6c 100644
--- a/src/simutrans/gui/components/gui_schedule.cc
+++ b/src/simutrans/gui/components/gui_schedule.cc
@@ -3,15 +3,21 @@
  * (see LICENSE.txt)
  */
 
+
+#include "gui_schedule.h"
+
 #include "../../simline.h"
 #include "../../simcolor.h"
 #include "../../simintr.h"
 #include "../../simhalt.h"
+#include "../../simconvoi.h"
+
 #include "../../world/simworld.h"
 #include "../../tool/simmenu.h"
-#include "../../simconvoi.h"
+
 #include "../../display/simgraph.h"
 #include "../../display/viewport.h"
+#include "../../display/font.h"
 
 #include "../../utils/simstring.h"
 #include "../../utils/cbuffer.h"
@@ -35,8 +41,6 @@
 #include "gui_timeinput.h"
 #include "gui_component.h"
 
-#include "gui_schedule.h"
-
 static karte_ptr_t welt;
 
 #define DELETE_FLAG (0x8000)
diff --git a/src/simutrans/gui/components/gui_scrollbar.cc b/src/simutrans/gui/components/gui_scrollbar.cc
index 5972bb64d..5b3ba6d04 100644
--- a/src/simutrans/gui/components/gui_scrollbar.cc
+++ b/src/simutrans/gui/components/gui_scrollbar.cc
@@ -6,6 +6,7 @@
 #include "../../simdebug.h"
 #include "../../simcolor.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../simskin.h"
 #include "../../macros.h"
 #include "../../descriptor/skin_desc.h"
diff --git a/src/simutrans/gui/components/gui_scrolled_list.cc b/src/simutrans/gui/components/gui_scrolled_list.cc
index 6aab2aecc..365a67435 100644
--- a/src/simutrans/gui/components/gui_scrolled_list.cc
+++ b/src/simutrans/gui/components/gui_scrolled_list.cc
@@ -13,6 +13,7 @@
 #include "../simwin.h"
 
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../descriptor/skin_desc.h"
 #include "../../simskin.h"
 
@@ -31,7 +32,7 @@ scr_size gui_scrolled_list_t::const_text_scrollitem_t::get_min_size() const
 {
 	if (!is_editable()) {
 		const char* text = get_text();
-		return scr_size(2*D_H_SPACE + (text ? gfx->calc_text_width(text) : D_BUTTON_WIDTH), LINESPACE);
+		return scr_size(2*D_H_SPACE + (text ? font_t::default_font->calc_text_width(text) : D_BUTTON_WIDTH), LINESPACE);
 	}
 	else {
 		return scr_size(D_BUTTON_WIDTH, LINESPACE);
@@ -50,11 +51,11 @@ void gui_scrolled_list_t::const_text_scrollitem_t::draw(scr_coord pos)
 	if(selected) {
 		// selected element
 		gfx->draw_rect_clipped( pos.x+D_H_SPACE/2, pos.y-1, get_size().w-D_H_SPACE, get_size().h + 1, (focused ? SYSCOL_LIST_BACKGROUND_SELECTED_F : SYSCOL_LIST_BACKGROUND_SELECTED_NF), true CLIP_NUM_DEFAULT);
-		gfx->draw_text_clipped( pos.x+D_H_SPACE, pos.y, get_text(), ALIGN_LEFT, (focused ? SYSCOL_LIST_TEXT_SELECTED_FOCUS : SYSCOL_LIST_TEXT_SELECTED_NOFOCUS), true);
+		gfx->draw_text_clipped( pos.x+D_H_SPACE, pos.y, get_text(), font_t::default_font, ALIGN_LEFT, (focused ? SYSCOL_LIST_TEXT_SELECTED_FOCUS : SYSCOL_LIST_TEXT_SELECTED_NOFOCUS), true);
 	}
 	else {
 		// normal text
-		gfx->draw_text_clipped( pos.x+D_H_SPACE, pos.y, get_text(), ALIGN_LEFT, get_color(), true);
+		gfx->draw_text_clipped( pos.x+D_H_SPACE, pos.y, get_text(), font_t::default_font, ALIGN_LEFT, get_color(), true);
 	}
 }
 
diff --git a/src/simutrans/gui/components/gui_tab_panel.cc b/src/simutrans/gui/components/gui_tab_panel.cc
index cf2bfb1a2..9497058de 100644
--- a/src/simutrans/gui/components/gui_tab_panel.cc
+++ b/src/simutrans/gui/components/gui_tab_panel.cc
@@ -9,6 +9,7 @@
 #include "../../simevent.h"
 #include "../../dataobj/environment.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../simcolor.h"
 #include "../simwin.h"
 #include "../../world/simworld.h"
@@ -55,7 +56,7 @@ void gui_tab_panel_t::set_size(scr_size size)
 	for(tab & i : tabs) {
 		i.x_offset = required_size.w - 4;
 		if( i.title ) {
-			i.width = D_H_SPACE*2 + gfx->calc_text_width( i.title );
+			i.width = D_H_SPACE*2 + font_t::default_font->calc_text_width( i.title );
 			required_size.h = max( required_size.h, LINESPACE + D_V_SPACE );
 		}
 		else if( i.img ) {
@@ -289,7 +290,7 @@ void gui_tab_panel_t::draw(scr_coord parent_pos)
 			gfx->draw_vline_clipped(text_x+iter.width-1, ypos+3, required_size.h-4, SYSCOL_SHADOW,    true CLIP_NUM_DEFAULT);
 
 			if(text) {
-				gfx->draw_text_clipped(text_x+D_H_SPACE, text_y+2, text, ALIGN_LEFT, SYSCOL_TEXT, true);
+				gfx->draw_text_clipped(text_x+D_H_SPACE, text_y+2, text, font_t::default_font, ALIGN_LEFT, SYSCOL_TEXT, true);
 			}
 			else {
 				scr_coord_val const y = ypos   - iter.img->get_pic()->y + required_size.h / 2 - iter.img->get_pic()->h / 2 + 1;
@@ -306,7 +307,7 @@ void gui_tab_panel_t::draw(scr_coord parent_pos)
 			gfx->draw_vline_clipped(text_x+iter.width-1, ypos+1, required_size.h-2, SYSCOL_SHADOW,    true CLIP_NUM_DEFAULT);
 
 			if(text) {
-				gfx->draw_text_clipped(text_x+D_H_SPACE, text_y, text, ALIGN_LEFT, SYSCOL_TEXT_HIGHLIGHT, true);
+				gfx->draw_text_clipped(text_x+D_H_SPACE, text_y, text, font_t::default_font, ALIGN_LEFT, SYSCOL_TEXT_HIGHLIGHT, true);
 			}
 			else {
 				scr_coord_val const y = ypos   - iter.img->get_pic()->y + required_size.h / 2 - iter.img->get_pic()->h / 2 - 1;
diff --git a/src/simutrans/gui/components/gui_textarea.cc b/src/simutrans/gui/components/gui_textarea.cc
index ee3641ea2..ed36e0024 100644
--- a/src/simutrans/gui/components/gui_textarea.cc
+++ b/src/simutrans/gui/components/gui_textarea.cc
@@ -7,6 +7,7 @@
 
 #include "gui_textarea.h"
 #include "../../display/simgraph.h"
+#include "../../display/font.h"
 #include "../../simdebug.h"
 #include "../../simcolor.h"
 #include "../../simskin.h"
@@ -62,7 +63,7 @@ scr_size gui_textarea_t::calc_size() const
 			do {
 				next = strchr(buf, '\n');
 				const size_t len = next ? next-buf : 99999;
-				const int px_len = gfx->calc_text_width_n(buf, len);
+				const int px_len = font_t::default_font->calc_text_width_n(buf, len);
 
 				if(  px_len > x_size  ) {
 					x_size = px_len;
@@ -109,11 +110,11 @@ void gui_textarea_t::draw(scr_coord offset)
 			int px_len;
 			if (  -LINESPACE <= draw_y  &&  draw_y <= gfx->get_screen_size().h + LINESPACE) {
 				// draw when in screen area
-				px_len = gfx->draw_text_clipped_n(x, draw_y, buf, ALIGN_LEFT | DT_CLIP, SYSCOL_TEXT, true, len CLIP_NUM_DEFAULT);
+				px_len = gfx->draw_text_clipped_n(x, draw_y, buf, font_t::default_font, ALIGN_LEFT | DT_CLIP, SYSCOL_TEXT, true, len CLIP_NUM_DEFAULT);
 			}
 			else {
 				// track required length when out of screen area
-				px_len = gfx->calc_text_width_n(buf, len);
+				px_len = font_t::default_font->calc_text_width_n(buf, len);
 			}
 			if(px_len>x_size) {
 				x_size = px_len;
diff --git a/src/simutrans/gui/components/gui_textinput.cc b/src/simutrans/gui/components/gui_textinput.cc
index 93dfdbf1e..3acd4f667 100644
--- a/src/simutrans/gui/components/gui_textinput.cc
+++ b/src/simutrans/gui/components/gui_textinput.cc
@@ -8,6 +8,7 @@
 #include "gui_textinput.h"
 #include "../simwin.h"
 #include "../../dataobj/translator.h"
+#include "../../display/font.h"
 #include "../../utils/simstring.h"
 #include "../../utils/unicode.h"
 #include "../../sys/simsys.h"
@@ -53,12 +54,13 @@ size_t gui_textinput_t::calc_cursor_pos(const int x)
 {
 	size_t new_cursor_pos = 0;
 	if(  text  ) {
-		const char* tmp_text = text;
-		uint8 byte_length = 0;
-		uint8 pixel_width = 0;
+		const char*   tmp_text       = text;
+		uint8         byte_length    = 0;
+		scr_coord_val pixel_width    = 0;
 		scr_coord_val current_offset = 0;
 		const scr_coord_val adjusted_offset = x - 1 + scroll_offset;
-		while(  gfx->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  adjusted_offset>(current_offset+(pixel_width>>1))  ) {
+
+		while(  font_t::default_font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)  &&  adjusted_offset>(current_offset+(pixel_width>>1))  ) {
 			current_offset += pixel_width;
 			new_cursor_pos += byte_length;
 		}
@@ -102,7 +104,7 @@ void gui_textinput_t::set_composition_status( char *c, int start, int length )
 			composition_target_length = length;
 
 			const scr_coord gui_xy = win_get_pos( win_get_top() );
-			const int offset_to_target = gfx->calc_text_width_n( composition.get_str(), composition_target_start );
+			const int offset_to_target = font_t::default_font->calc_text_width_n( composition.get_str(), composition_target_start );
 			const scr_coord_val x = pos.x + gui_xy.x + get_current_cursor_x() + offset_to_target;
 			const scr_coord_val y = pos.x + gui_xy.y + D_TITLEBAR_HEIGHT;
 			dr_notify_input_pos({ x, y });
@@ -190,10 +192,10 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 						// Ctrl key pressed -> skip over to the start of the previous word (as delimited by space(s))
 						if(  IS_CONTROL_PRESSED(ev)  ) {
 							const char* tmp_text = text + head_cursor_pos;
-							uint8 byte_length = 0;
-							uint8 pixel_width = 0;
+							uint8         byte_length = 0;
+							scr_coord_val pixel_width = 0;
 							// first skip over all contiguous space characters to the left
-							while(  head_cursor_pos>0  &&  gfx->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)==SIM_KEYCODE_SPACE  ) {
+							while(  head_cursor_pos>0  &&  font_t::default_font->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)==SIM_KEYCODE_SPACE  ) {
 								head_cursor_pos -= byte_length;
 							}
 							// revert text pointer for further processing
@@ -201,7 +203,7 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 								tmp_text += byte_length;
 							}
 							// then skip over all contiguous non-space characters further to the left
-							while(  head_cursor_pos>0  &&  gfx->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
+							while(  head_cursor_pos>0  &&  font_t::default_font->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
 								head_cursor_pos -= byte_length;
 							}
 						}
@@ -219,10 +221,10 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 						// Ctrl key pressed -> skip over to the start of the next word (as delimited by space(s))
 						if(  IS_CONTROL_PRESSED(ev)  ) {
 							const char* tmp_text = text + head_cursor_pos;
-							uint8 byte_length = 0;
-							uint8 pixel_width = 0;
+							uint8         byte_length = 0;
+							scr_coord_val pixel_width = 0;
 							// first skip over all contiguous non-space characters to the right
-							while(  head_cursor_pos<len  &&  gfx->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
+							while(  head_cursor_pos<len  &&  font_t::default_font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
 								head_cursor_pos += byte_length;
 							}
 							// revert text pointer for further processing
@@ -230,7 +232,7 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 								tmp_text -= byte_length;
 							}
 							// then skip over all contiguous space characters further to the right
-							while(  head_cursor_pos<len  &&  gfx->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)==SIM_KEYCODE_SPACE  ) {
+							while(  head_cursor_pos<len  &&  font_t::default_font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)==SIM_KEYCODE_SPACE  ) {
 								head_cursor_pos += byte_length;
 							}
 						}
@@ -456,7 +458,7 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 		// use mouse *click* position; update both head and tail cursors
 		tail_cursor_pos = 0;
 		if(  text  ) {
-			tail_cursor_pos = head_cursor_pos = gfx->calc_text_index_for_width( text, ev->click_pos.x - 2 + scroll_offset );
+			tail_cursor_pos = head_cursor_pos = font_t::default_font->calc_text_index_for_width( text, ev->click_pos.x - 2 + scroll_offset );
 		}
 		cursor_reference_time = dr_time(); // update reference time for cursor blinking
 		return true;
@@ -471,7 +473,7 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 		// use mouse *move* position; update head cursor only in order to enable text selection
 		head_cursor_pos = 0;
 		if(  text  ) {
-			head_cursor_pos = gfx->calc_text_index_for_width( text, ev->mouse_pos.x - 1 + scroll_offset );
+			head_cursor_pos = font_t::default_font->calc_text_index_for_width( text, ev->mouse_pos.x - 1 + scroll_offset );
 		}
 		cursor_reference_time = dr_time(); // update reference time for cursor blinking
 		return true;
@@ -487,14 +489,14 @@ bool gui_textinput_t::infowin_event(const event_t *ev)
 		// for tail cursor pos -> skip over all contiguous non-space characters to the left
 		const char* tmp_text = text + tail_cursor_pos;
 		uint8 byte_length;
-		uint8 pixel_width;
-		while(  tail_cursor_pos>0  &&  gfx->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
+		scr_coord_val pixel_width;
+		while(  tail_cursor_pos>0  &&  font_t::default_font->get_prev_char_with_metrics(tmp_text, text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
 			tail_cursor_pos -= byte_length;
 		}
 		// for head cursor pos -> skip over all contiguous non-space characters to the right
 		const size_t len = strlen(text);
 		tmp_text = text + head_cursor_pos;
-		while(  head_cursor_pos<len  &&  gfx->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
+		while(  head_cursor_pos<len  &&  font_t::default_font->get_next_char_with_metrics(tmp_text, byte_length, pixel_width)!=SIM_KEYCODE_SPACE  ) {
 			head_cursor_pos += byte_length;
 		}
 	}
@@ -605,9 +607,9 @@ void gui_textinput_t::display_with_cursor(scr_coord offset, bool cursor_active,
 	if (display_text) {
 
 		// recalculate scroll offset
-		const int text_width = gfx->calc_text_width(display_text);
+		const int text_width = font_t::default_font->calc_text_width(text);
 		const scr_coord_val view_width = size.w - 3;
-		const int cursor_offset = cursor_active ? gfx->calc_text_width_n(display_text, head_cursor_pos) : 0;
+		const int cursor_offset = cursor_active ? font_t::default_font->calc_text_width_n(text, head_cursor_pos) : 0;
 
 		if (text_width <= view_width) {
 			// case : text is shorter than displayable width of the text input
@@ -650,40 +652,40 @@ void gui_textinput_t::display_with_cursor(scr_coord offset, bool cursor_active,
 		const int y_offset = pos.y+offset.y+D_GET_CENTER_ALIGN_OFFSET(LINESPACE,size.h);
 
 		// display text (before composition)
-		gfx->draw_text_clipped_n(x_base_offset, y_offset, display_text, ALIGN_LEFT | DT_CLIP, display_color, true, head_cursor_pos CLIP_NUM_DEFAULT);
-		int x_offset = gfx->calc_text_width_n(text, head_cursor_pos);
+		gfx->draw_text_clipped_n(x_base_offset, y_offset, text, font_t::default_font, ALIGN_LEFT | DT_CLIP, enabled ? textcol : SYSCOL_EDIT_TEXT_DISABLED, true, head_cursor_pos CLIP_NUM_DEFAULT);
+		int x_offset = font_t::default_font->calc_text_width_n(text, head_cursor_pos);
 
 		// IME text to display?
 		if (composition.len()) {
 			//	assert(head_cursor_pos==tail_cursor_pos);
 
-			gfx->draw_text_clipped(x_base_offset + x_offset, y_offset, composition.get_str(), ALIGN_LEFT | DT_CLIP, display_color, true);
+			gfx->draw_text_clipped(x_base_offset+x_offset, y_offset, composition.get_str(), font_t::default_font, ALIGN_LEFT | DT_CLIP, enabled ? textcol : SYSCOL_EDIT_TEXT_DISABLED, true);
 
 			// draw underline
-			int composition_width = gfx->calc_text_width(composition.get_str());
+			int composition_width = font_t::default_font->calc_text_width(composition.get_str());
 			gfx->draw_line(x_base_offset + x_offset, y_offset + LINESPACE, x_base_offset + x_offset + composition_width, y_offset + LINESPACE - 1, display_color);
 
 			// mark targeted part in a similar manner to selected text
-			int start_offset = gfx->calc_text_width_n(composition.get_str(), composition_target_start);
-			int highlight_width = gfx->calc_text_width_n(composition.get_str()+composition_target_start, composition_target_length);
+			int start_offset    = font_t::default_font->calc_text_width_n(composition.get_str(), composition_target_start);
+			int highlight_width = font_t::default_font->calc_text_width_n(composition.get_str()+composition_target_start, composition_target_length);
 			gfx->draw_rect_clipped(x_base_offset+x_offset+start_offset, y_offset, highlight_width, LINESPACE, SYSCOL_EDIT_BACKGROUND_SELECTED, true CLIP_NUM_DEFAULT);
-			gfx->draw_text_clipped_n(x_base_offset+x_offset+start_offset, y_offset, composition.get_str()+composition_target_start, ALIGN_LEFT|DT_CLIP, SYSCOL_EDIT_TEXT_SELECTED, false, composition_target_length CLIP_NUM_DEFAULT);
+			gfx->draw_text_clipped_n(x_base_offset+x_offset+start_offset, y_offset, composition.get_str()+composition_target_start, font_t::default_font, ALIGN_LEFT|DT_CLIP, SYSCOL_EDIT_TEXT_SELECTED, false, composition_target_length CLIP_NUM_DEFAULT);
 
 			x_offset += composition_width;
 		}
 
 		// display text (after composition)
-		gfx->draw_text_clipped(x_base_offset + x_offset, y_offset, display_text + head_cursor_pos, ALIGN_LEFT | DT_CLIP, display_color, true);
+		gfx->draw_text_clipped(x_base_offset+x_offset, y_offset, text+head_cursor_pos, font_t::default_font, ALIGN_LEFT | DT_CLIP, enabled ? textcol : SYSCOL_EDIT_TEXT_DISABLED, true);
 
 		if (cursor_active && enabled) {
 			// display selected text block with light grey text on charcoal bounding box
 			if (head_cursor_pos != tail_cursor_pos) {
 				const size_t start_pos = min(head_cursor_pos, tail_cursor_pos);
 				size_t end_pos = ::max(head_cursor_pos, tail_cursor_pos);
-				const scr_coord_val start_offset = gfx->calc_text_width_n(display_text, start_pos);
-				const scr_coord_val highlight_width = gfx->calc_text_width_n(display_text + start_pos, end_pos - start_pos);
+				const scr_coord_val start_offset    = font_t::default_font->calc_text_width_n(text, start_pos);
+				const scr_coord_val highlight_width = font_t::default_font->calc_text_width_n(text+start_pos, end_pos-start_pos);
 				gfx->draw_rect_clipped(x_base_offset + start_offset, y_offset, highlight_width, LINESPACE, SYSCOL_EDIT_BACKGROUND_SELECTED, true CLIP_NUM_DEFAULT);
-				gfx->draw_text_clipped_n(x_base_offset + start_offset, y_offset, display_text + start_pos, ALIGN_LEFT | DT_CLIP, SYSCOL_EDIT_TEXT_SELECTED, false, end_pos - start_pos CLIP_NUM_DEFAULT);
+				gfx->draw_text_clipped_n(x_base_offset+start_offset, y_offset, text+start_pos, font_t::default_font, ALIGN_LEFT|DT_CLIP, SYSCOL_EDIT_TEXT_SELECTED, false, end_pos-start_pos CLIP_NUM_DEFAULT);
 			}
 
 			// display blinking cursor
@@ -730,7 +732,7 @@ bool gui_hidden_textinput_t::infowin_event(const event_t *ev)
 		}
 		// acting on release causes unwanted recalculations of cursor position for long strings and (cursor_offset>0)
 		// moreover, only (click) or (release) event happened inside textinput, the other one could lie outside
-		sint16 asterix_width = gfx->calc_text_width_n("*", 1);
+		sint16 asterix_width = font_t::default_font->calc_text_width_n("*", 1);
 		head_cursor_pos = 0;
 		if (  text  ) {
 			head_cursor_pos = min( strlen(text), ev->click_pos.x/asterix_width );
@@ -774,7 +776,7 @@ void gui_hidden_textinput_t::display_with_cursor(scr_coord const offset, bool, b
 			}
 			c = utf8_decoder_t::decode((utf8 const *&)text_pos);
 			if(c) {
-				xpos += gfx->draw_text_clipped( xpos, pos.y+offset.y+1+(size.h-LINESPACE)/2, "*", ALIGN_LEFT | DT_CLIP, textcol, true);
+				xpos += gfx->draw_text_clipped( xpos, pos.y+offset.y+1+(size.h-LINESPACE)/2, "*", font_t::default_font, ALIGN_LEFT | DT_CLIP, textcol, true);
 			}
 		}
 		while(  text_pos < end  &&  c != UNICODE_NUL  );
diff --git a/src/simutrans/gui/display_settings.cc b/src/simutrans/gui/display_settings.cc
index d8f1077a4..da3635917 100644
--- a/src/simutrans/gui/display_settings.cc
+++ b/src/simutrans/gui/display_settings.cc
@@ -15,6 +15,7 @@
 #include "../obj/baum.h"
 #include "../obj/zeiger.h"
 #include "../display/simgraph.h"
+#include "../display/font.h"
 #include "../tool/simmenu.h"
 #include "../player/simplay.h"
 #include "../utils/simstring.h"
diff --git a/src/simutrans/gui/gui_theme.cc b/src/simutrans/gui/gui_theme.cc
index 53e40c1fd..3b8caafdc 100644
--- a/src/simutrans/gui/gui_theme.cc
+++ b/src/simutrans/gui/gui_theme.cc
@@ -7,16 +7,19 @@
 
 
 #include "gui_theme.h"
+
+#include "components/gui_button.h"
+#include "components/gui_tab_panel.h"
+
 #include "../world/simworld.h"
 #include "../simskin.h"
 #include "../tool/simmenu.h"
 #include "../sys/simsys.h"
 #include "../dataobj/environment.h"
 #include "../dataobj/tabfile.h"
-#include "components/gui_button.h"
-#include "components/gui_tab_panel.h"
-#include "../descriptor/skin_desc.h"
 #include "../dataobj/pakset_manager.h"
+#include "../descriptor/skin_desc.h"
+#include "../display/font.h"
 
 
 /**
@@ -414,7 +417,7 @@ bool gui_theme_t::themes_init(const char *file_name, bool init_fonts, bool init_
 	// reload current font if requested size differs and we are allowed to do so
 	uint8 new_size = contents.get_int("font_size", env_t::fontsize );
 	if(  init_fonts  &&  new_size!=0  &&  LINESPACE!=new_size  ) {
-		if(  gfx->load_font(env_t::fontname.c_str(), false)  ) {
+		if(  font_t::load_default_font(env_t::fontname.c_str(), false)  ) {
 			env_t::fontsize = new_size;
 		}
 	}
diff --git a/src/simutrans/gui/halt_info.cc b/src/simutrans/gui/halt_info.cc
index 66c83aaed..a63851046 100644
--- a/src/simutrans/gui/halt_info.cc
+++ b/src/simutrans/gui/halt_info.cc
@@ -16,6 +16,7 @@
 #include "../simintr.h"
 #include "../display/simgraph.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 #include "../tool/simmenu.h"
 #include "../simskin.h"
 #include "../simline.h"
@@ -27,6 +28,7 @@
 #include "../dataobj/translator.h"
 #include "../dataobj/loadsave.h"
 
+#include "../display/font.h"
 #include "../player/simplay.h"
 
 #include "../vehicle/vehicle.h"
@@ -467,13 +469,13 @@ void halt_info_t::update_components()
 		lb_happy[2].update();
 	}
 	else {
-		if(  gfx->font_has_character( 0x263A )  ) {
+		if(  font_t::default_font->has_glyph_for_character( 0x263A )  ) {
 			utf8 happy[4], unhappy[4];
 			happy[ utf16_to_utf8( 0x263A, happy ) ] = 0;
 			unhappy[ utf16_to_utf8( 0x2639, unhappy ) ] = 0;
 			lb_happy[0].buf().printf(translator::translate("Passengers %d %s, %d %s, %d no route"), halt->get_pax_happy(), happy, halt->get_pax_unhappy(), unhappy, halt->get_pax_no_route());
 		}
-		else if(  gfx->font_has_character( 30 )  ) {
+		else if(  font_t::default_font->has_glyph_for_character( 30 )  ) {
 			lb_happy[0].buf().printf(translator::translate("Passengers %d %c, %d %c, %d no route"), halt->get_pax_happy(), 30, halt->get_pax_unhappy(), 31, halt->get_pax_no_route());
 		}
 		else {
diff --git a/src/simutrans/gui/kennfarbe.cc b/src/simutrans/gui/kennfarbe.cc
index 4acc81888..3ba8c7a66 100644
--- a/src/simutrans/gui/kennfarbe.cc
+++ b/src/simutrans/gui/kennfarbe.cc
@@ -8,6 +8,7 @@
 #include "../simskin.h"
 #include "../dataobj/environment.h"
 #include "../dataobj/translator.h"
+#include "../display/font.h"
 #include "../player/simplay.h"
 #include "components/gui_label.h"
 #include "components/gui_image.h"
@@ -22,7 +23,7 @@ class choose_color_button_t : public button_t
 public:
 	choose_color_button_t() : button_t()
 	{
-		w = max(D_BUTTON_HEIGHT, gfx->get_char_width('X') + D_BUTTON_PADDINGS_X);
+		w = max(D_BUTTON_HEIGHT, font_t::default_font->get_char_width('X') + D_BUTTON_PADDINGS_X);
 	}
 	scr_size get_min_size() const OVERRIDE
 	{
@@ -136,7 +137,6 @@ bool farbengui_t::action_triggered( gui_action_creator_t *comp,value_t /* */)
 			delete w;
 			return true;
 		}
-
 	}
 
 	return false;
diff --git a/src/simutrans/gui/map_frame.cc b/src/simutrans/gui/map_frame.cc
index dbb45e09e..f850ed49c 100644
--- a/src/simutrans/gui/map_frame.cc
+++ b/src/simutrans/gui/map_frame.cc
@@ -16,6 +16,8 @@
 #include "../world/simworld.h"
 #include "../display/simgraph.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
+
 #include "../simcolor.h"
 #include "../builder/fabrikbauer.h"
 #include "../builder/goods_manager.h"
diff --git a/src/simutrans/gui/minimap.cc b/src/simutrans/gui/minimap.cc
index ae8ddac8e..aa63704ec 100644
--- a/src/simutrans/gui/minimap.cc
+++ b/src/simutrans/gui/minimap.cc
@@ -32,6 +32,7 @@
 #include "../display/scr_coord.h"
 #include "../display/simgraph.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 #include "../utils/simrandom.h"
 #include "../player/simplay.h"
 
@@ -1234,9 +1235,9 @@ const fabrik_t* minimap_t::draw_factory_connections(const fabrik_t* const fab, b
 
 				scr_coord boxpos = end + scr_coord(10, 0);
 				const char * name = translator::translate(fab2->get_name());
-				int name_width = gfx->calc_text_width(name) + (LINESPACE/2);
+				int name_width = font_t::default_font->calc_text_width(name) + (LINESPACE/2);
 				boxpos.x = clamp( boxpos.x, pos.x, pos.x+get_size().w-name_width );
-				gfx->draw_textbox3d_clipped(boxpos.x, boxpos.y, gfx->palette_lookup(5), gfx->palette_lookup(COL_WHITE), name, true CLIP_NUM_DEFAULT);
+				gfx->draw_textbox3d_clipped(boxpos.x, boxpos.y, name, font_t::default_font, gfx->palette_lookup(5), gfx->palette_lookup(COL_WHITE), true CLIP_NUM_DEFAULT);
 			}
 		}
 	}
@@ -1685,7 +1686,7 @@ void minimap_t::draw(scr_coord pos)
 
 			scr_coord p = map_to_screen_coord( stadt->get_pos() );
 			p += pos;
-			gfx->draw_text_clipped( p.x, p.y, name, ALIGN_LEFT, col, true );
+			gfx->draw_text_clipped( p.x, p.y, name, font_t::default_font, ALIGN_LEFT, col, true );
 		}
 	}
 
@@ -1773,7 +1774,7 @@ void minimap_t::draw(scr_coord pos)
 	if(  display_station.is_bound()  ) {
 		scr_coord temp_stop = map_to_screen_coord( display_station->get_basis_pos() );
 		temp_stop = temp_stop + pos;
-		gfx->draw_textbox3d_clipped( temp_stop.x + 10, temp_stop.y + 7, gfx->palette_lookup(display_station->get_owner()->get_player_color1()+3), gfx->palette_lookup(COL_WHITE), display_station->get_name(), false CLIP_NUM_DEFAULT);
+		gfx->draw_textbox3d_clipped( temp_stop.x + 10, temp_stop.y + 7, display_station->get_name(), font_t::default_font, gfx->palette_lookup(display_station->get_owner()->get_player_color1()+3), gfx->palette_lookup(COL_WHITE), false CLIP_NUM_DEFAULT);
 	}
 
 	// zoom/resize "selection box" in map
@@ -1826,10 +1827,10 @@ void minimap_t::draw(scr_coord pos)
 			scr_coord fabpos = map_to_screen_coord( fab->get_pos().get_2d() );
 			scr_coord boxpos = fabpos + scr_coord(10, 0);
 			const char * name = translator::translate(fab->get_name());
-			int name_width = gfx->calc_text_width(name) + (LINESPACE/2);
+			int name_width = font_t::default_font->calc_text_width(name) + (LINESPACE/2);
 			boxpos.x = clamp( boxpos.x, 0, 0+get_size().w-name_width );
 			boxpos += pos;
-			gfx->draw_textbox3d_clipped(boxpos.x, boxpos.y, gfx->palette_lookup(10), gfx->palette_lookup(COL_WHITE), name, true CLIP_NUM_DEFAULT);
+			gfx->draw_textbox3d_clipped(boxpos.x, boxpos.y, name, font_t::default_font, gfx->palette_lookup(10), gfx->palette_lookup(COL_WHITE), true CLIP_NUM_DEFAULT);
 		}
 
 		for (int i = win_get_open_count() - 1; i >= 0; i--) {
diff --git a/src/simutrans/gui/money_frame.cc b/src/simutrans/gui/money_frame.cc
index ca7ceab23..7894ce6a3 100644
--- a/src/simutrans/gui/money_frame.cc
+++ b/src/simutrans/gui/money_frame.cc
@@ -14,6 +14,8 @@
 #include "../player/ai_scripted.h"
 #include "../simdebug.h"
 #include "../display/simgraph.h"
+#include "../display/font.h"
+
 #include "../simcolor.h"
 #include "../utils/simstring.h"
 #include "../dataobj/translator.h"
diff --git a/src/simutrans/gui/savegame_frame.cc b/src/simutrans/gui/savegame_frame.cc
index c1cb4325e..42327eff9 100644
--- a/src/simutrans/gui/savegame_frame.cc
+++ b/src/simutrans/gui/savegame_frame.cc
@@ -16,6 +16,8 @@
 #include "../utils/searchfolder.h"
 #include "../dataobj/environment.h"
 #include "../dataobj/translator.h"
+#include "../display/font.h"
+
 #include "banner.h"
 
 #define L_DEFAULT_ROWS       (12)   // Number of file entries to show as default
@@ -31,7 +33,7 @@ public:
 	del_button_t() : button_t()
 	{
 		init(button_t::roundbox, "X");
-		w = max(D_BUTTON_HEIGHT, gfx->get_char_width('X') + D_BUTTON_PADDINGS_X);
+		w = max(D_BUTTON_HEIGHT, font_t::default_font->get_char_width('X') + D_BUTTON_PADDINGS_X);
 	}
 	scr_size get_min_size() const OVERRIDE
 	{
diff --git a/src/simutrans/gui/simwin.cc b/src/simutrans/gui/simwin.cc
index b2773fea7..c4adcda86 100644
--- a/src/simutrans/gui/simwin.cc
+++ b/src/simutrans/gui/simwin.cc
@@ -11,6 +11,7 @@
 #include "../simevent.h"
 #include "../display/simgraph.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 #include "../tool/simmenu.h"
 #include "../simskin.h"
 #include "../sys/simsys.h"
@@ -216,7 +217,7 @@ static int display_gadget_box(sint8 code,
 		else if(  code == SKIN_GADGET_PINNED  ) {
 			gadget_text = "S";
 		}
-		gfx->draw_text( x+4, y+4, gadget_text, ALIGN_LEFT, SYSCOL_TEXT, false );
+		gfx->draw_text( x+4, y+4, gadget_text, font_t::default_font, ALIGN_LEFT, SYSCOL_TEXT, false );
 	}
 
 	int side = x+REVERSE_GADGETS*D_GADGET_WIDTH-1;
@@ -352,9 +353,9 @@ static void win_draw_window_title(const scr_coord pos, const scr_size size,
 	// Draw the gadgets and then move left and draw text.
 	flags.gotopos = (welt_pos != koord3d::invalid);
 	int width = display_gadget_boxes( &flags, pos.x+(REVERSE_GADGETS?0:size.w-D_GADGET_WIDTH), pos.y, lighter, darker, gadget_state, sticky, goto_pushed );
-	int titlewidth = gfx->draw_text_clipped( pos.x + (REVERSE_GADGETS?width+4:4), pos.y+(D_TITLEBAR_HEIGHT-LINEASCENT)/2, text, ALIGN_LEFT, text_color, false );
+	int titlewidth = gfx->draw_text_clipped( pos.x + (REVERSE_GADGETS?width+4:4), pos.y+(D_TITLEBAR_HEIGHT-LINEASCENT)/2, text, font_t::default_font, ALIGN_LEFT, text_color, false );
 	if(  flags.gotopos  ) {
-		gfx->draw_text_clipped( pos.x + (REVERSE_GADGETS?width+4:4)+titlewidth+8, pos.y+(D_TITLEBAR_HEIGHT-LINEASCENT)/2, welt_pos.get_fullstr(), ALIGN_LEFT, text_color, false );
+		gfx->draw_text_clipped( pos.x + (REVERSE_GADGETS?width+4:4)+titlewidth+8, pos.y+(D_TITLEBAR_HEIGHT-LINEASCENT)/2, welt_pos.get_fullstr(), font_t::default_font, ALIGN_LEFT, text_color, false );
 	}
 	POP_CLIP();
 }
@@ -1865,8 +1866,8 @@ void win_poll_event(event_t* const ev)
 		ev->ev_class = IGNORE_EVENT;
 
 		// now see how much of the status text fits the display
-		scr_coord_val time_width = gfx->calc_text_width(tick_to_string(wl->get_ticks()));
-		scr_coord_val player_width = gfx->calc_text_width(wl->get_active_player()->get_name());
+		scr_coord_val time_width   = font_t::default_font->calc_text_width(tick_to_string(wl->get_ticks()));
+		scr_coord_val player_width = font_t::default_font->calc_text_width(wl->get_active_player()->get_name());
 
 		char buffer[128];
 		if (env_t::player_finance_display_account) {
@@ -1876,8 +1877,8 @@ void win_poll_event(event_t* const ev)
 			money_to_string(buffer, (double)world()->get_active_player()->get_finance()->get_netwealth() / 100.0);
 		}
 
-		scr_coord_val money_width = gfx->calc_text_width(buffer);
-		scr_coord_val position_width = gfx->calc_text_width(wl->get_zeiger()->get_pos().get_str());
+		scr_coord_val money_width    = font_t::default_font->calc_text_width(buffer);
+		scr_coord_val position_width = font_t::default_font->calc_text_width(wl->get_zeiger()->get_pos().get_str());
 
 		// if too long shorten radically
 		status_show_compact = (time_width + player_width + money_width + position_width) * 1.2 > ev->new_window_size.w;
@@ -2019,20 +2020,20 @@ void win_display_flush(double konto)
 				// display tooltip when current owner is invalid or when it is within visible duration
 				uint32 elapsed_time;
 				if(  !tooltip_owner  ||  ((elapsed_time=dr_time()-tooltip_register_time)>env_t::tooltip_delay  &&  elapsed_time<=env_t::tooltip_delay+env_t::tooltip_duration)  ) {
-					const sint16 width = gfx->calc_text_width(tooltip_text)+(LINESPACE/2);
+					const sint16 width = font_t::default_font->calc_text_width(tooltip_text)+(LINESPACE/2);
 					scr_coord pos{ tooltip_xpos, tooltip_ypos };
 					win_clamp_xywh_position( NULL, pos, scr_size( width, (LINESPACE*9)/7 ), true );
-					gfx->draw_textbox3d_clipped( pos.x, pos.y, env_t::tooltip_color, env_t::tooltip_textcolor, tooltip_text, true CLIP_NUM_DEFAULT);
+					gfx->draw_textbox3d_clipped( pos.x, pos.y, tooltip_text, font_t::default_font, env_t::tooltip_color, env_t::tooltip_textcolor, true CLIP_NUM_DEFAULT);
 					if(wl) {
 						wl->set_background_dirty();
 					}
 				}
 			}
 			else if(!static_tooltip_text.empty()) {
-				const sint16 width = gfx->calc_text_width(static_tooltip_text.c_str())+ (LINESPACE/2);
+				const sint16 width = font_t::default_font->calc_text_width(static_tooltip_text.c_str())+ (LINESPACE/2);
 				scr_coord pos = get_mouse_pos();
 				win_clamp_xywh_position( NULL, pos, scr_size(width, (LINESPACE*9)/7), true);
-				gfx->draw_textbox3d_clipped(pos.x, pos.y, env_t::tooltip_color, env_t::tooltip_textcolor, static_tooltip_text.c_str(), true CLIP_NUM_DEFAULT);
+				gfx->draw_textbox3d_clipped(pos.x, pos.y, static_tooltip_text.c_str(), font_t::default_font, env_t::tooltip_color, env_t::tooltip_textcolor, true CLIP_NUM_DEFAULT);
 				if(wl) {
 					wl->set_background_dirty();
 				}
@@ -2179,8 +2180,8 @@ void win_display_flush(double konto)
 	}
 #endif
 
-	left_border  += 4 + gfx->draw_text(left_border,  status_bar_text_y, time, ALIGN_LEFT,  SYSCOL_STATUSBAR_TEXT, true);
-	right_border -= 4 + gfx->draw_text(right_border, status_bar_text_y, info, ALIGN_RIGHT, SYSCOL_STATUSBAR_TEXT, true);
+	left_border  += 4 + gfx->draw_text(left_border,  status_bar_text_y, time, font_t::default_font, ALIGN_LEFT,  SYSCOL_STATUSBAR_TEXT, true);
+	right_border -= 4 + gfx->draw_text(right_border, status_bar_text_y, info, font_t::default_font, ALIGN_RIGHT, SYSCOL_STATUSBAR_TEXT, true);
 
 	/* Since the visual center jumps left and right with proportional fonts, we quantisze by 16 pixel
 	 */
@@ -2190,7 +2191,7 @@ void win_display_flush(double konto)
 	if(wl->get_active_player()) {
 		char buffer[256];
 		scr_coord_val textwidth_pl = 0;
-		textwidth_pl = D_H_SPACE + gfx->calc_text_width(wl->get_active_player()->get_name());
+		textwidth_pl = D_H_SPACE + font_t::default_font->calc_text_width(wl->get_active_player()->get_name());
 		if (status_show_compact) {
 			number_to_string_fit(buffer, konto, 0, 10);
 			strcat(buffer, "$");
@@ -2199,12 +2200,12 @@ void win_display_flush(double konto)
 			money_to_string(buffer, konto);
 		}
 
-		scr_coord_val textwidth_mn = (gfx->calc_text_width(buffer) + 15) & 0xFFFFFFF0ul;
+		scr_coord_val textwidth_mn = (font_t::default_font->calc_text_width(buffer) + 15) & 0xFFFFFFF0ul;
 		if (textwidth_mn + textwidth_pl < right_border - left_border) {
 			// everything fits
 			left_border += ( (right_border - left_border) - (textwidth_mn + textwidth_pl)  ) / 2;
-			left_border += D_H_SPACE + gfx->draw_text(left_border, status_bar_text_y, wl->get_active_player()->get_name(), ALIGN_LEFT, PLAYER_FLAG | gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark), true);
-			gfx->draw_text(left_border, status_bar_text_y, buffer, ALIGN_LEFT, konto >= 0.0 ? MONEY_PLUS : MONEY_MINUS, true);
+			left_border += D_H_SPACE + gfx->draw_text(left_border, status_bar_text_y, wl->get_active_player()->get_name(), font_t::default_font, ALIGN_LEFT, PLAYER_FLAG | gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark), true);
+			gfx->draw_text(left_border, status_bar_text_y, buffer, font_t::default_font, ALIGN_LEFT, konto >= 0.0 ? MONEY_PLUS : MONEY_MINUS, true);
 		}
 		else {
 			// no space => only money
@@ -2212,10 +2213,10 @@ void win_display_flush(double konto)
 			scr_coord_val width_left = (right_border - left_border - textwidth_mn);
 			if (width_left > 50) {
 				scr_rect r(left_border, status_bar_text_y, width_left-D_H_SPACE, LINESPACE);
-				gfx->draw_text_ellipsis(r, wl->get_active_player()->get_name(), ALIGN_LEFT, PLAYER_FLAG | gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark), true);
+				gfx->draw_text_ellipsis(r, wl->get_active_player()->get_name(), font_t::default_font, ALIGN_LEFT, PLAYER_FLAG | gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark), true);
 				left_border += width_left;
 				// normal color
-				gfx->draw_text(left_border, status_bar_text_y, buffer, ALIGN_LEFT, konto >= 0.0 ? MONEY_PLUS : MONEY_MINUS, true);
+				gfx->draw_text(left_border, status_bar_text_y, buffer, font_t::default_font, ALIGN_LEFT, konto >= 0.0 ? MONEY_PLUS : MONEY_MINUS, true);
 			}
 			else {
 				// just money in player color, no player name
@@ -2227,7 +2228,7 @@ void win_display_flush(double konto)
 					number_to_string_fit(buffer, konto, 0, 5);
 					strcat(buffer, "$");
 				}
-				gfx->draw_text(left_border, status_bar_text_y, buffer, ALIGN_LEFT, konto >= 0.0 ? gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark) : MONEY_MINUS, true);
+				gfx->draw_text(left_border, status_bar_text_y, buffer, font_t::default_font, ALIGN_LEFT, konto >= 0.0 ? gfx->palette_lookup(wl->get_active_player()->get_player_color1() + env_t::gui_player_color_dark) : MONEY_MINUS, true);
 			}
 		}
 	}
@@ -2269,7 +2270,7 @@ void win_load_font(const char *fname, uint8 fontsize)
 	bool force_reload = fontsize != env_t::fontsize;
 	env_t::fontsize = fontsize;
 
-	if (gfx->load_font(fname, force_reload) ) {
+	if (font_t::load_default_font(fname, force_reload) ) {
 		// successfull
 		gui_theme_t::themes_init( env_t::default_theme, false, false );
 
@@ -2280,7 +2281,7 @@ void win_load_font(const char *fname, uint8 fontsize)
 	}
 	else {
 		// restore old font
-		gfx->load_font(env_t::fontname.c_str(), true);
+		font_t::load_default_font(env_t::fontname.c_str(), true);
 	}
 	win_redraw_world();
 }
@@ -2336,7 +2337,7 @@ void win_set_tooltip(scr_coord pos, const char *text, const void *const owner, c
 	}
 
 	if (text) {
-		const scr_size tt_size = scr_size(gfx->calc_text_width(text), LINESPACE + 2);
+		const scr_size tt_size = scr_size(font_t::default_font->calc_text_width(text), LINESPACE + 2);
 		win_clamp_xywh_position(NULL, pos, tt_size, true);
 		pos.y += LINESPACE / 2 + 1;
 	}
diff --git a/src/simutrans/gui/sprachen.cc b/src/simutrans/gui/sprachen.cc
index 5e4f4e73c..d20942f2a 100644
--- a/src/simutrans/gui/sprachen.cc
+++ b/src/simutrans/gui/sprachen.cc
@@ -67,7 +67,7 @@ void sprachengui_t::init_font_from_lang()
 	size_t len;
 	utf16 testfor_this_character = utf8_decoder_t::decode(new_world, len);
 
-	bool reload_font = !gfx->font_has_character(testfor_this_character);
+	bool reload_font = !font_t::default_font->has_glyph_for_character(testfor_this_character);
 
 	if(reload_font) {
 		if (env_t::fontsize == 11) {
@@ -90,7 +90,7 @@ void sprachengui_t::init_font_from_lang()
 				do {
 					std::string fname = FONT_PATH_X;
 					fname += prop_font_file_name;
-					ok = gfx->load_font(fname.c_str(), false);
+					ok = font_t::load_default_font(fname.c_str(), false);
 					f = strtok(NULL, ";");
 				} while (!ok && f);
 				dr_chdir(env_t::user_dir);
@@ -240,7 +240,7 @@ bool sprachengui_t::action_triggered( gui_action_creator_t *comp, value_t p)
 				// we only show matching fonts for this language
 				const utf8 *new_world = (const utf8 *)translator::translate("Beenden");
 				size_t len;
-				if (!gfx->font_has_character(utf8_decoder_t::decode(new_world, len))) {
+				if (!font_t::default_font->has_glyph_for_character(utf8_decoder_t::decode(new_world, len))) {
 					// load a matching font ...
 					create_win(new loadfont_frame_t(), w_info, magic_font);
 				}
diff --git a/src/simutrans/gui/vehiclelist_frame.cc b/src/simutrans/gui/vehiclelist_frame.cc
index 380547ace..d73c3bf42 100644
--- a/src/simutrans/gui/vehiclelist_frame.cc
+++ b/src/simutrans/gui/vehiclelist_frame.cc
@@ -14,7 +14,7 @@
 #include "../world/simworld.h"
 
 #include "../display/simgraph.h"
-
+#include "../display/font.h"
 #include "../dataobj/translator.h"
 
 #include "../descriptor/goods_desc.h"
@@ -48,11 +48,11 @@ vehiclelist_stats_t::vehiclelist_stats_t(const vehicle_desc_t *v) :
 	height = r.h;
 
 	// name is the widest entry in column 1
-	name_width = gfx->calc_text_width( translator::translate( veh->get_name(), world()->get_settings().get_name_language_id() ) );
+	name_width = font_t::default_font->calc_text_width( translator::translate( veh->get_name(), world()->get_settings().get_name_language_id() ) );
 	if( veh->get_power() > 0 ) {
 		char str[ 256 ];
 		sprintf( str, " (%s)", translator::translate( vehicle_builder_t::engine_type_names[ veh->get_engine_type() + 1 ] ) );
-		name_width += gfx->calc_text_width( str );
+		name_width += font_t::default_font->calc_text_width( str );
 	}
 	scr_coord_val name_h = LINESPACE;
 
@@ -86,7 +86,7 @@ vehiclelist_stats_t::vehiclelist_stats_t(const vehicle_desc_t *v) :
 		}
 	}
 
-	const scr_size text1_size = gfx->calc_multiline_text_size(part1);
+	const scr_size text1_size = font_t::default_font->calc_multiline_text_size(part1);
 	col1_width = text1_size.w + D_H_SPACE;
 
 	// column 2
@@ -101,7 +101,7 @@ vehiclelist_stats_t::vehiclelist_stats_t(const vehicle_desc_t *v) :
 		part2.printf( translator::translate( "Constructed by %s" ), copyright );
 	}
 
-	const scr_size text2_size = gfx->calc_multiline_text_size(part2);
+	const scr_size text2_size = font_t::default_font->calc_multiline_text_size(part2);
 	col2_width = text2_size.w;
 
 	// we need to find out manually, if we have extra text to show
@@ -137,6 +137,7 @@ void vehiclelist_stats_t::draw( scr_coord offset )
 	int dx = gfx->draw_text(
 		offset.x, offset.y,
 		translator::translate( veh->get_name(), world()->get_settings().get_name_language_id() ),
+		font_t::default_font,
 		ALIGN_LEFT|DT_CLIP,
 		veh->is_future(month) ? SYSCOL_TEXT_HIGHLIGHT : (veh->is_available(month) ? SYSCOL_TEXT : gui_theme_t::gui_color_obsolete),
 		false
@@ -145,7 +146,7 @@ void vehiclelist_stats_t::draw( scr_coord offset )
 	if( veh->get_power() > 0 ) {
 		char str[ 256 ];
 		sprintf( str, " (%s)", translator::translate( vehicle_builder_t::engine_type_names[ veh->get_engine_type() + 1 ] ) );
-		gfx->draw_text( offset.x+dx, offset.y, str, ALIGN_LEFT|DT_CLIP, SYSCOL_TEXT, false );
+		gfx->draw_text( offset.x+dx, offset.y, str, font_t::default_font, ALIGN_LEFT|DT_CLIP, SYSCOL_TEXT, false );
 	}
 
 	// maybe there are detailed text to the vehicle?
@@ -156,9 +157,9 @@ void vehiclelist_stats_t::draw( scr_coord offset )
 	}
 
 	// now the rest in two columns
-	gfx->draw_multiline_text( offset.x, yyy, part1, SYSCOL_TEXT );
+	gfx->draw_multiline_text( offset.x,              yyy, part1, font_t::default_font, SYSCOL_TEXT );
 
-	gfx->draw_multiline_text( offset.x + col1_width, yyy, part2, SYSCOL_TEXT );
+	gfx->draw_multiline_text( offset.x + col1_width, yyy, part2, font_t::default_font, SYSCOL_TEXT );
 }
 
 
diff --git a/src/simutrans/player/simplay.cc b/src/simutrans/player/simplay.cc
index 3cec367e5..2827ae369 100644
--- a/src/simutrans/player/simplay.cc
+++ b/src/simutrans/player/simplay.cc
@@ -222,9 +222,11 @@ void player_t::display_messages()
 
 	for(income_message_t* const m : messages) {
 
-		const scr_coord scr_pos = vp->get_screen_coord(koord3d(m->pos,welt->lookup_hgt(m->pos)),koord(0,m->alter >> 4)) + scr_coord((gfx->get_tile_raster_width()-gfx->calc_text_width_n(m->str, 0x7FFF))/2,0);
+		const scr_coord scr_pos = vp->get_screen_coord(koord3d(m->pos, welt->lookup_hgt(m->pos)), koord(0, m->alter >> 4))
+			+ scr_coord((gfx->get_tile_raster_width() - font_t::default_font->calc_text_width_n(m->str, 0x7FFF))/2, 0);
+
+		gfx->draw_text_shadowed( scr_pos.x, scr_pos.y, m->str, font_t::default_font, PLAYER_FLAG|gfx->palette_lookup(player_color_1+3), gfx->palette_lookup(COL_BLACK), true);
 
-		gfx->draw_text_shadowed( scr_pos.x, scr_pos.y, PLAYER_FLAG|gfx->palette_lookup(player_color_1+3), gfx->palette_lookup(COL_BLACK), m->str, true);
 		if(  m->pos.x < 3  ||  m->pos.y < 3  ) {
 			// very close to border => renew background
 			welt->set_background_dirty();
diff --git a/src/simutrans/simfab.cc b/src/simutrans/simfab.cc
index 91bd90b05..dd30f6fb6 100644
--- a/src/simutrans/simfab.cc
+++ b/src/simutrans/simfab.cc
@@ -50,6 +50,8 @@
 
 #include "gui/simwin.h"
 #include "display/simgraph.h"
+#include "display/font.h"
+
 
 // Fabrik_t
 
diff --git a/src/simutrans/simhalt.cc b/src/simutrans/simhalt.cc
index 170690fd2..ce96b49d8 100644
--- a/src/simutrans/simhalt.cc
+++ b/src/simutrans/simhalt.cc
@@ -29,6 +29,8 @@
 #include "descriptor/goods_desc.h"
 #include "descriptor/tunnel_desc.h"
 
+#include "display/font.h"
+
 #include "ground/boden.h"
 #include "ground/grund.h"
 #include "ground/wasser.h"
diff --git a/src/simutrans/simloadingscreen.cc b/src/simutrans/simloadingscreen.cc
index 0a787f324..7d636ba72 100644
--- a/src/simutrans/simloadingscreen.cc
+++ b/src/simutrans/simloadingscreen.cc
@@ -10,6 +10,7 @@
 #include "descriptor/skin_desc.h"
 #include "simskin.h"
 #include "display/simgraph.h"
+#include "display/font.h"
 #include "simevent.h"
 #include "dataobj/environment.h"
 #include "simticker.h"
@@ -82,7 +83,7 @@ void loadingscreen_t::display()
 		dr_prepare_flush();
 
 		if(  info  ) {
-			gfx->draw_text( half_width, bar_y - LINESPACE - 2, info, ALIGN_CENTER_H, gfx->palette_lookup(COL_WHITE), true );
+			gfx->draw_text( half_width, bar_y - LINESPACE - 2, info, font_t::default_font, ALIGN_CENTER_H, gfx->palette_lookup(COL_WHITE), true );
 		}
 
 		// outline
@@ -96,7 +97,7 @@ void loadingscreen_t::display()
 		gfx->draw_rect( quarter_width, bar_y + 4, bar_len,  bar_height - 8, SYSCOL_LOADINGBAR_PROGRESS, true );
 
 		if(  what  ) {
-			gfx->draw_text( half_width, bar_text_y, what, ALIGN_CENTER_H, SYSCOL_TEXT_HIGHLIGHT, false );
+			gfx->draw_text( half_width, bar_text_y, what, font_t::default_font, ALIGN_CENTER_H, SYSCOL_TEXT_HIGHLIGHT, false );
 		}
 
 		dr_flush();
diff --git a/src/simutrans/simmain.cc b/src/simutrans/simmain.cc
index ee8ceb052..ef2cc1aa9 100644
--- a/src/simutrans/simmain.cc
+++ b/src/simutrans/simmain.cc
@@ -47,6 +47,7 @@
 
 #include "sys/simsys.h"
 #include "display/simgraph.h"
+#include "display/font.h"
 #include "simevent.h"
 
 #include "simversion.h"
@@ -191,7 +192,7 @@ static void show_times(karte_t *welt, main_view_t *view)
 
 	ms = dr_time();
 	for (i = 0;  i < 300000;  i++) {
-		gfx->draw_text_clipped_n(100, 120, "Dies ist ein kurzer Textetxt ...", 0, 0, false, -1 CLIP_NUM_DEFAULT);
+		gfx->draw_text_clipped_n(100, 120, "Dies ist ein kurzer Textetxt ...", font_t::default_font, 0, 0, false, -1 CLIP_NUM_DEFAULT);
 	}
 	dbg->message("show_times()", "draw_text_clipped_n() %i iterations took %li ms", i, dr_time() - ms );
 
@@ -252,11 +253,12 @@ static void show_times(karte_t *welt, main_view_t *view)
 
 
 // some routines for the modal display
-static bool never_quit() { return false; }
 static bool no_language() { return translator::get_language()!=-1; }
-static utf16 testfor_this_character = 0;
-static bool no_font() { return gfx->font_has_character(testfor_this_character); }
+
 #if COLOUR_DEPTH != 0
+static bool never_quit() { return false; }
+static utf16 testfor_this_character = 0;
+static bool no_font() { return font_t::default_font->has_glyph_for_character(testfor_this_character); }
 static bool empty_objfilename() { return !env_t::pak_name.empty() ||  pakinstaller_t::finish_install; }
 static bool finish_install() { return pakinstaller_t::finish_install; }
 #endif
@@ -916,6 +918,20 @@ int simu_main(int argc, char** argv)
 		}
 	}
 
+#if COLOUR_DEPTH != 0
+	// init, load, and check fonts
+	if (!font_t::load_default_font(env_t::fontname.c_str(), false)) {
+		env_t::fontname = dr_get_system_font();
+		if (!font_t::load_default_font(env_t::fontname.c_str(), false)) {
+			env_t::fontname = FONT_PATH_X "cyr.bdf";
+			if (!font_t::load_default_font(env_t::fontname.c_str(), false)) {
+				dr_fatal_notify("No fonts found!");
+				return EXIT_FAILURE;
+			}
+		}
+	}
+#endif
+
 	simgraph_type_t preferred_renderer_type =
 #if COLOUR_DEPTH == 0
 		SIMGRAPH_TYPE_NULL;
@@ -1265,7 +1281,7 @@ int simu_main(int argc, char** argv)
 		const utf8 *new_world = (const utf8 *)translator::translate("Beenden");
 		size_t len;
 		testfor_this_character = utf8_decoder_t::decode(new_world,len);
-		if (!gfx->font_has_character(testfor_this_character)) {
+		if (!font_t::default_font->has_glyph_for_character(testfor_this_character)) {
 			// not valid => show font selector
 			loadfont_frame_t* sel = new loadfont_frame_t();
 			destroy_all_win(true); // since eventually the successful load message is still there ....
diff --git a/src/simutrans/simticker.cc b/src/simutrans/simticker.cc
index bc9937cc6..6599c8f76 100644
--- a/src/simutrans/simticker.cc
+++ b/src/simutrans/simticker.cc
@@ -7,6 +7,7 @@
 #include "dataobj/environment.h"
 #include "simticker.h"
 #include "display/simgraph.h"
+#include "display/font.h"
 #include "simcolor.h"
 #include "tpl/slist_tpl.h"
 #include "utils/simstring.h"
@@ -97,7 +98,7 @@ void ticker::add_msg_node(const message_node_t& msg)
 		n.msg[i++] = 0;
 
 		n.xpos = next_pos;
-		n.w = gfx->calc_text_width(n.msg);
+		n.w = font_t::default_font->calc_text_width(n.msg);
 
 		next_pos += n.w + X_SPACING;
 		list.append(n);
@@ -178,7 +179,7 @@ void ticker::draw()
 	PUSH_CLIP( screen.w-dx_since_last_draw, start_y, dx_since_last_draw, TICKER_HEIGHT );
 	for(node & n : list) {
 		if (n.xpos < screen.w) {
-			gfx->draw_text_clipped(n.xpos, start_y + TICKER_V_SPACE, n.msg, ALIGN_LEFT, n.get_player_color(welt), true);
+			gfx->draw_text_clipped(n.xpos, start_y + TICKER_V_SPACE, n.msg, font_t::default_font, ALIGN_LEFT, n.get_player_color(welt), true);
 		}
 	}
 	POP_CLIP();
@@ -205,7 +206,7 @@ void ticker::redraw()
 	gfx->draw_rect(0, start_y, screen.w, TICKER_HEIGHT, SYSCOL_TICKER_BACKGROUND, true);
 	for(node & n : list) {
 		if (n.xpos < screen.w) {
-			gfx->draw_text_clipped(n.xpos, start_y + TICKER_V_SPACE, n.msg, ALIGN_LEFT, n.color, true);
+			gfx->draw_text_clipped(n.xpos, start_y + TICKER_V_SPACE, n.msg, font_t::default_font, ALIGN_LEFT, n.color, true);
 		}
 	}
 }
diff --git a/src/simutrans/simticker.h b/src/simutrans/simticker.h
index cb3ff9a60..7bad8d601 100644
--- a/src/simutrans/simticker.h
+++ b/src/simutrans/simticker.h
@@ -9,6 +9,8 @@
 
 #include "simcolor.h"
 #include "display/simgraph.h"
+#include "display/font.h"
+
 
 #define TICKER_V_SPACE (2) // Vertical offset of ticker text
 #define TICKER_HEIGHT  (LINESPACE+2*TICKER_V_SPACE)
@@ -16,6 +18,8 @@
 
 class koord3d;
 struct message_node_t;
+
+
 /**
  * A very simple scrolling news ticker.
  */
diff --git a/src/simutrans/sys/simsys_s2.cc b/src/simutrans/sys/simsys_s2.cc
index e4f9cb344..a26b0c0c3 100644
--- a/src/simutrans/sys/simsys_s2.cc
+++ b/src/simutrans/sys/simsys_s2.cc
@@ -23,19 +23,20 @@ extern char **__argv;
 
 #include "simsys.h"
 
-#include "../macros.h"
-#include "../simversion.h"
-#include "../simevent.h"
-#include "../display/simgraph.h"
-#include "../simdebug.h"
 #include "../dataobj/environment.h"
-#include "../gui/simwin.h"
+#include "../display/font.h"
+#include "../display/simgraph.h"
 #include "../gui/components/gui_component.h"
 #include "../gui/components/gui_textinput.h"
-#include "../simintr.h"
-#include "../world/simworld.h"
+#include "../gui/simwin.h"
+#include "../macros.h"
 #include "../music/music.h"
+#include "../simdebug.h"
+#include "../simevent.h"
+#include "../simintr.h"
+#include "../simversion.h"
 #include "../utils/unicode.h"
+#include "../world/simworld.h"
 
 
 // Maybe Linux is not fine too, had critical bugs...
diff --git a/src/simutrans/tool/simtool-dialogs.h b/src/simutrans/tool/simtool-dialogs.h
index 56d805788..c9311842b 100644
--- a/src/simutrans/tool/simtool-dialogs.h
+++ b/src/simutrans/tool/simtool-dialogs.h
@@ -14,6 +14,8 @@
 #include "../dataobj/scenario.h"
 #include "../dataobj/environment.h"
 
+#include "../display/font.h"
+
 #include "../gui/baum_edit.h"
 #include "../gui/chat_frame.h"
 #include "../gui/citybuilding_edit.h"
@@ -663,12 +665,12 @@ public:
 			if (unread_count) {
 				char str[16];
 				sprintf(str, "%i", unread_count);
-				scr_coord_val txt_width = gfx->calc_text_width(str);
+				scr_coord_val txt_width = font_t::default_font->calc_text_width(str);
 				scr_coord_val width = max(LINEASCENT, txt_width + 2);
 				scr_coord_val xoff = env_t::iconsize.w - width - 1;
 				scr_coord_val yoff = env_t::iconsize.h - LINESPACE - 1;
 				gfx->draw_rounded_rect_clipped(pos.x + xoff, pos.y + yoff, width, LINESPACE, gfx->palette_lookup(COL_RED + 1), dirty);
-				gfx->draw_text(pos.x + xoff + D_GET_CENTER_ALIGN_OFFSET(txt_width, width), pos.y + yoff + 1, str, ALIGN_LEFT, gfx->palette_lookup(COL_WHITE), dirty);
+				gfx->draw_text(pos.x + xoff + D_GET_CENTER_ALIGN_OFFSET(txt_width, width), pos.y + yoff + 1, str, font_t::default_font, ALIGN_LEFT, gfx->palette_lookup(COL_WHITE), dirty);
 			}
 		}
 	}
diff --git a/src/simutrans/tool/simtool.cc b/src/simutrans/tool/simtool.cc
index 2831e78a7..077c19983 100644
--- a/src/simutrans/tool/simtool.cc
+++ b/src/simutrans/tool/simtool.cc
@@ -14,6 +14,7 @@
 #include "../simconvoi.h"
 #include "../gui/simwin.h"
 #include "../display/viewport.h"
+#include "../display/font.h"
 
 #include "../builder/fabrikbauer.h"
 #include "../builder/vehikelbauer.h"
@@ -5303,7 +5304,7 @@ void tool_build_roadsign_t::draw_after(scr_coord k, bool dirty) const
 		gfx->draw_img_blend(icon, k.x, k.y, TRANSPARENT50_FLAG|OUTLINE_FLAG|gfx->palette_lookup(COL_BLACK), false, dirty );
 		char level_str[16];
 		sprintf(level_str, "%i", signal[welt->get_active_player_nr()].spacing);
-		gfx->draw_text( k.x+4, k.y+4, level_str, ALIGN_LEFT, gfx->palette_lookup(COL_YELLOW), true );
+		gfx->draw_text( k.x+4, k.y+4, level_str, font_t::default_font, ALIGN_LEFT, gfx->palette_lookup(COL_YELLOW), true );
 	}
 }
 
@@ -7616,7 +7617,7 @@ void tool_show_underground_t::draw_after(scr_coord k, bool dirty) const
 		if(  default_param!=NULL  &&  grund_t::underground_mode==grund_t::ugm_level  ) {
 			char level_str[16];
 			sprintf( level_str, "%i", grund_t::underground_level );
-			gfx->draw_text( k.x+4, k.y+4, level_str, ALIGN_LEFT, gfx->palette_lookup(COL_YELLOW), true );
+			gfx->draw_text( k.x+4, k.y+4, level_str, font_t::default_font, ALIGN_LEFT, gfx->palette_lookup(COL_YELLOW), true );
 		}
 	}
 }
diff --git a/src/simutrans/vehicle/vehicle.cc b/src/simutrans/vehicle/vehicle.cc
index a4bce670e..6eaeb87d6 100644
--- a/src/simutrans/vehicle/vehicle.cc
+++ b/src/simutrans/vehicle/vehicle.cc
@@ -5,24 +5,25 @@
 
 #include "vehicle.h"
 
-#include "../simintr.h"
-#include "../world/simworld.h"
-#include "../simware.h"
-#include "../simconvoi.h"
-#include "../simhalt.h"
-#include "../dataobj/translator.h"
-#include "../simfab.h"
-#include "../player/simplay.h"
+#include "../builder/vehikelbauer.h"
+#include "../dataobj/environment.h"
+#include "../dataobj/pakset_manager.h"
 #include "../dataobj/schedule.h"
+#include "../dataobj/translator.h"
+#include "../display/font.h"
 #include "../gui/minimap.h"
 #include "../obj/crossing.h"
 #include "../obj/wolke.h"
-#include "../utils/cbuffer.h"
-#include "../dataobj/environment.h"
-#include "../dataobj/pakset_manager.h"
-#include "../builder/vehikelbauer.h"
 #include "../obj/zeiger.h"
+#include "../player/simplay.h"
+#include "../simconvoi.h"
+#include "../simfab.h"
+#include "../simhalt.h"
+#include "../simintr.h"
+#include "../simware.h"
+#include "../utils/cbuffer.h"
 #include "../utils/simstring.h"
+#include "../world/simworld.h"
 
 #include <cmath>
 
@@ -1248,7 +1249,7 @@ void vehicle_t::display_after(int xpos, int ypos, bool is_global) const
 			ypos += tile_raster_scale_y(get_yoff(), raster_width)+14;
 
 			if(ypos>LINESPACE+32  &&  ypos+LINESPACE < gfx->get_clip_rect(CLIP_NUM_DEFAULT_VALUE).yy) {
-				gfx->draw_textbox3d_clipped( xpos, ypos, color, gfx->palette_lookup(COL_BLACK), tooltip_text, true CLIP_NUM_DEFAULT);
+				gfx->draw_textbox3d_clipped( xpos, ypos, tooltip_text, font_t::default_font, color, gfx->palette_lookup(COL_BLACK), true CLIP_NUM_DEFAULT);
 			}
 		}
 	}
