[Scummvm-git-logs] scummvm master -> 3395af886f9750b6988ed45645376763a47a1494

dreammaster noreply at scummvm.org
Sun Mar 27 21:05:13 UTC 2022


This automated email contains information about 15 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
c6ddeae2df AGS: Expand error messages for Get/SetGlobalInt/String functions
ee119e9611 AGS: Safer impl of Set/GetGlobalString
5b56aecee4 AGS: Create a room placeholder to avoid crashes in game_start script
e1e2716d37 AGS: For room placeholder also set croom ptr to temp room status
db3e087526 AGS: Fixed play.globalscriptvars[] was not initialized on start
31e9bef490 AGS: Avoid crash trying to open files that don't exist
7132742e04 AGS: Reintroduce upstream's full alfont implementation
8e1a3d08db AGS: Add USE_FREETYPE2 guard to alfont
91bce9b2e9 AGS: Implement xor_mode/solid_mode
f34cf7ce67 AGS: Apply TTF ascender hack only by the engine's request
f4935dbf39 AGS: Force readjust TTF fonts if the OPT_ANTIALIASFONTS changes
5b10b7437c AGS: Added "ascender fixup" flag to the font init mode
84a54f5e8e AGS: Remade OPT_FONTLOADLOGIC into individual font's flags
4005849cf0 AGS: Updated build version (3.6.0.11)
3395af886f COMMON: Fix assert crash trying to open invalid fs nodes


Commit: c6ddeae2dfc796c2c538be14fa5499b9f0af3fd9
    https://github.com/scummvm/scummvm/commit/c6ddeae2dfc796c2c538be14fa5499b9f0af3fd9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:10-07:00

Commit Message:
AGS: Expand error messages for Get/SetGlobalInt/String functions

>From upstream c5cee80341ce1b66de865f624717f0922df8b3a7

Changed paths:
    engines/ags/engine/ac/global_game.cpp


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index afeb1c0e604..a80717fcc13 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -199,7 +199,7 @@ void FillSaveList(std::vector<SaveListItem> &saves, size_t max_count) {
 
 void SetGlobalInt(int index, int valu) {
 	if ((index < 0) | (index >= MAXGSVALUES))
-		quit("!SetGlobalInt: invalid index");
+		quitprintf("!SetGlobalInt: invalid index %d, supported range is %d - %d", index, 0, MAXGSVALUES - 1);
 
 	if (_GP(play).globalscriptvars[index] != valu) {
 		debug_script_log("GlobalInt %d set to %d", index, valu);
@@ -211,13 +211,13 @@ void SetGlobalInt(int index, int valu) {
 
 int GetGlobalInt(int index) {
 	if ((index < 0) | (index >= MAXGSVALUES))
-		quit("!GetGlobalInt: invalid index");
+		quitprintf("!GetGlobalInt: invalid index %d, supported range is %d - %d", index, 0, MAXGSVALUES - 1);
 	return _GP(play).globalscriptvars[index];
 }
 
 void SetGlobalString(int index, const char *newval) {
 	if ((index < 0) | (index >= MAXGLOBALSTRINGS))
-		quit("!SetGlobalString: invalid index");
+		quitprintf("!SetGlobalString: invalid index %d, supported range is %d - %d", index, 0, MAXGLOBALSTRINGS - 1);
 	debug_script_log("GlobalString %d set to '%s'", index, newval);
 	strncpy(_GP(play).globalstrings[index], newval, MAX_MAXSTRLEN);
 	// truncate it to 200 chars, to be sure
@@ -226,7 +226,7 @@ void SetGlobalString(int index, const char *newval) {
 
 void GetGlobalString(int index, char *strval) {
 	if ((index < 0) | (index >= MAXGLOBALSTRINGS))
-		quit("!GetGlobalString: invalid index");
+		quitprintf("!GetGlobalString: invalid index %d, supported range is %d - %d", index, 0, MAXGLOBALSTRINGS - 1);
 	strcpy(strval, _GP(play).globalstrings[index]);
 }
 


Commit: ee119e96114181a628cb14fbd1b47d5956e987d6
    https://github.com/scummvm/scummvm/commit/ee119e96114181a628cb14fbd1b47d5956e987d6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:10-07:00

Commit Message:
AGS: Safer impl of Set/GetGlobalString

>From upstream dfdba6c4648267ea19136420ae8019de984869a4

Changed paths:
    engines/ags/engine/ac/global_game.cpp


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index a80717fcc13..50fb9eef052 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -219,15 +219,13 @@ void SetGlobalString(int index, const char *newval) {
 	if ((index < 0) | (index >= MAXGLOBALSTRINGS))
 		quitprintf("!SetGlobalString: invalid index %d, supported range is %d - %d", index, 0, MAXGLOBALSTRINGS - 1);
 	debug_script_log("GlobalString %d set to '%s'", index, newval);
-	strncpy(_GP(play).globalstrings[index], newval, MAX_MAXSTRLEN);
-	// truncate it to 200 chars, to be sure
-	_GP(play).globalstrings[index][MAX_MAXSTRLEN - 1] = 0;
+	snprintf(_GP(play).globalstrings[index], MAX_MAXSTRLEN, "%s", newval);
 }
 
 void GetGlobalString(int index, char *strval) {
 	if ((index < 0) | (index >= MAXGLOBALSTRINGS))
 		quitprintf("!GetGlobalString: invalid index %d, supported range is %d - %d", index, 0, MAXGLOBALSTRINGS - 1);
-	strcpy(strval, _GP(play).globalstrings[index]);
+	snprintf(strval, MAX_MAXSTRLEN, "%s", _GP(play).globalstrings[index]);
 }
 
 // TODO: refactor this method, and use same shared procedure at both normal stop/startup and in RunAGSGame


Commit: 5b56aecee411b89121aebe3edff243f06877e278
    https://github.com/scummvm/scummvm/commit/5b56aecee411b89121aebe3edff243f06877e278
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:11-07:00

Commit Message:
AGS: Create a room placeholder to avoid crashes in game_start script

>From upstream f3a6b65a80987f9fe993f5449538eb98a86c6353

Changed paths:
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/room.h
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/main/game_start.cpp


diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index a29c520c9a0..4e7fe009538 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -937,6 +937,16 @@ void new_room(int newnum, CharacterInfo *forchar) {
 	load_new_room(newnum, forchar);
 }
 
+void set_room_placeholder() {
+	_GP(thisroom).InitDefaults();
+	std::shared_ptr<Bitmap> dummy_bg(new Bitmap(1, 1, 8));
+	_GP(thisroom).BgFrames[0].Graphic = dummy_bg;
+	_GP(thisroom).HotspotMask = dummy_bg;
+	_GP(thisroom).RegionMask = dummy_bg;
+	_GP(thisroom).WalkAreaMask = dummy_bg;
+	_GP(thisroom).WalkBehindMask = dummy_bg;
+}
+
 int find_highest_room_entered() {
 	int qq, fndas = -1;
 	for (qq = 0; qq < MAX_ROOMS; qq++) {
diff --git a/engines/ags/engine/ac/room.h b/engines/ags/engine/ac/room.h
index aa42ac18eaa..9ed38a4d1a4 100644
--- a/engines/ags/engine/ac/room.h
+++ b/engines/ags/engine/ac/room.h
@@ -52,6 +52,9 @@ void  save_room_data_segment();
 void  unload_old_room();
 void  load_new_room(int newnum, CharacterInfo *forchar);
 void  new_room(int newnum, CharacterInfo *forchar);
+// Sets up a placeholder room object; this is used to avoid occasional crashes
+// in case an API function was called that needs to access a room, while no real room is loaded
+void  set_room_placeholder();
 int   find_highest_room_entered();
 void  first_room_initialization();
 void  check_new_room();
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 9bacfe6cd8b..e14e4ed5c57 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -493,6 +493,8 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	// load the room the game was saved in
 	if (_G(displayed_room) >= 0)
 		load_new_room(_G(displayed_room), nullptr);
+	else
+		set_room_placeholder();
 
 	update_polled_stuff_if_runtime();
 
diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index 7e89a78e2c2..e0d4bfe78cc 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -73,6 +73,7 @@ void start_game_load_savegame_on_startup() {
 }
 
 void start_game() {
+	set_room_placeholder();
 	set_cursor_mode(MODE_WALK);
 	_GP(mouse).SetPosition(Point(160, 100));
 	newmusic(0);


Commit: e1e2716d37c7a37abeb6f63edef8b51209990cfb
    https://github.com/scummvm/scummvm/commit/e1e2716d37c7a37abeb6f63edef8b51209990cfb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:12-07:00

Commit Message:
AGS: For room placeholder also set croom ptr to temp room status

>From upstream 518d08888eebf63f40460d21bd8560b979ed2565

Changed paths:
    engines/ags/engine/ac/room.cpp


diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 4e7fe009538..364de3c6676 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -412,6 +412,12 @@ HError LoadRoomScript(RoomStruct *room, int newnum) {
 	return HError::None();
 }
 
+static void reset_temp_room() {
+	_GP(troom).FreeScriptData();
+	_GP(troom).FreeProperties();
+	_GP(troom) = RoomStatus();
+}
+
 // forchar = playerchar on NewRoom, or NULL if restore saved game
 void load_new_room(int newnum, CharacterInfo *forchar) {
 
@@ -523,11 +529,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 	// setup objects
 	if (forchar != nullptr) {
 		// if not restoring a game, always reset this room
-		_GP(troom).beenhere = 0;
-		_GP(troom).FreeScriptData();
-		_GP(troom).FreeProperties();
-		memset(&_GP(troom).hotspot_enabled[0], 1, MAX_ROOM_HOTSPOTS);
-		memset(&_GP(troom).region_enabled[0], 1, MAX_ROOM_REGIONS);
+		reset_temp_room();
 	}
 	if ((newnum >= 0) & (newnum < MAX_ROOMS))
 		_G(croom) = getRoomStatus(newnum);
@@ -945,6 +947,8 @@ void set_room_placeholder() {
 	_GP(thisroom).RegionMask = dummy_bg;
 	_GP(thisroom).WalkAreaMask = dummy_bg;
 	_GP(thisroom).WalkBehindMask = dummy_bg;
+	reset_temp_room();
+	_G(croom) = &_GP(troom);
 }
 
 int find_highest_room_entered() {


Commit: db3e0875265af85ff0e4e69e1c2fb6c5c29dbd2a
    https://github.com/scummvm/scummvm/commit/db3e0875265af85ff0e4e69e1c2fb6c5c29dbd2a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:12-07:00

Commit Message:
AGS: Fixed play.globalscriptvars[] was not initialized on start

>From upstream b5c8feb3f70d35eebbab30d80d08f1c901081be2

Changed paths:
    engines/ags/engine/main/engine.cpp


diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index c7ec7de90fb..32df5b34ff9 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -804,7 +804,8 @@ void engine_init_game_settings() {
 	// reset graphical script vars (they're still used by some games)
 	for (ee = 0; ee < MAXGLOBALVARS; ee++)
 		_GP(play).globalvars[ee] = 0;
-
+	for (ee = 0; ee < MAXGSVALUES; ee++)
+		_GP(play).globalscriptvars[ee] = 0;
 	for (ee = 0; ee < MAXGLOBALSTRINGS; ee++)
 		_GP(play).globalstrings[ee][0] = 0;
 


Commit: 31e9bef4905f66542d59cb0b010b1fdc6e4dc188
    https://github.com/scummvm/scummvm/commit/31e9bef4905f66542d59cb0b010b1fdc6e4dc188
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:12-07:00

Commit Message:
AGS: Avoid crash trying to open files that don't exist

Changed paths:
    engines/ags/shared/util/file_stream.cpp


diff --git a/engines/ags/shared/util/file_stream.cpp b/engines/ags/shared/util/file_stream.cpp
index a03477e0084..9e595bdfbfd 100644
--- a/engines/ags/shared/util/file_stream.cpp
+++ b/engines/ags/shared/util/file_stream.cpp
@@ -172,11 +172,13 @@ void FileStream::Open(const String &file_name, FileOpenMode open_mode, FileWorkM
 		} else {
 			// First try to open file in game folder
 			Common::File *f = new Common::File();
-			if (!f->open(getFSNode(file_name.GetCStr()))) {
+			Common::FSNode fsNode = getFSNode(file_name.GetCStr());
+
+			if (fsNode.exists() && f->open(fsNode)) {
+				_file = f;
+			} else {
 				delete f;
 				_file = nullptr;
-			} else {
-				_file = f;
 			}
 		}
 


Commit: 7132742e04805b31a5226edacfac45ac92ce011b
    https://github.com/scummvm/scummvm/commit/7132742e04805b31a5226edacfac45ac92ce011b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:12-07:00

Commit Message:
AGS: Reintroduce upstream's full alfont implementation

Changed paths:
    engines/ags/lib/alfont/alfont.cpp
    engines/ags/lib/alfont/alfont.h
    engines/ags/lib/allegro/color.h
    engines/ags/lib/allegro/draw.cpp
    engines/ags/lib/allegro/draw.h
    engines/ags/lib/allegro/system.h
    engines/ags/lib/allegro/unicode.cpp
    engines/ags/lib/allegro/unicode.h
    engines/ags/shared/font/ttf_font_renderer.cpp


diff --git a/engines/ags/lib/alfont/alfont.cpp b/engines/ags/lib/alfont/alfont.cpp
index 21ed7b97527..b9a281cc4e5 100644
--- a/engines/ags/lib/alfont/alfont.cpp
+++ b/engines/ags/lib/alfont/alfont.cpp
@@ -19,107 +19,4967 @@
  *
  */
 
-#include "common/file.h"
-#include "graphics/fonts/ttf.h"
-#include "graphics/fonts/winfont.h"
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "common/scummsys.h"
 #include "ags/lib/alfont/alfont.h"
-#include "ags/ags.h"
-#include "ags/globals.h"
-#include "ags/shared/ac/game_setup_struct.h"
-#include "ags/engine/ac/display.h"
+#include "ags/lib/allegro/color.h"
+#include "ags/lib/allegro/draw.h"
+#include "ags/lib/allegro/gfx.h"
+#include "ags/lib/allegro/unicode.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
 
 namespace AGS3 {
 
-Graphics::Font *ALFONT_FONT::getFont() {
-#ifdef USE_FREETYPE2
-	if (!_fonts.contains(_size)) {
-		// Instantiate the raw TTF data into a font of the given size
-		Graphics::TTFRenderMode renderMode = Graphics::kTTFRenderModeMonochrome;
-		if (ShouldAntiAliasText())
-			renderMode = Graphics::kTTFRenderModeLight;
-		Graphics::Font *font = Graphics::loadTTFFont(_ttfData, _size, Graphics::kTTFSizeModeCharacter, 0, renderMode);
-		if (!font) {
-			// Try WinFont as TTFFont may fail loading those
-			Graphics::WinFont *winfont = new Graphics::WinFont();
-			if (winfont->loadFromFON(_ttfData))
-				font = winfont;
+#undef TRUE
+#undef FALSE
+#define TRUE  -1
+#define FALSE  0
+
+/* structs */
+struct _ALFONT_CACHED_GLYPH {
+	char is_cached;
+	int width, height, aawidth, aaheight;
+	int left, top, aaleft, aatop;
+	int advancex, advancey;
+	int mono_available, aa_available;
+	byte *bmp;
+	byte *aabmp;
+};
+
+struct ALFONT_FONT {
+	FT_Face face;           /* face */
+	int face_h;             /* face height */
+	int real_face_h;        /* real face height */
+	int face_ascender;      /* face ascender */
+	char *data;             /* if loaded from memory, the data chunk */
+	int data_size;          /* and its size */
+	int ch_spacing;         /* extra spacing */
+	int num_fixed_sizes;    /* -1 if scalable, >=0 if fixed */
+	_ALFONT_CACHED_GLYPH *cached_glyphs;  /* array to know which glyphs have been cached */
+	int *fixed_sizes;       /* array with the fixed sizes */
+	char *language;		  /* language */
+	int type;				  /* Code Convert(Please Use TYPE_WIDECHAR for ASCII to UNICODE) */
+	int outline_top;		  /* Font top outline width */
+	int outline_bottom;	  /* Font bottom outline width */
+	int outline_right;	  /* Font right outline width */
+	int outline_left;		  /* Font left outline width */
+	int outline_color;	  /* Font outline color */
+	int outline_hollow;	  /* Font hollow(TRUE/FALSE) */
+	int style;			  /* Font Style(STYLE_STANDARD/STYLE_ITALIC/STYLE_BOLD/STYLE_BOLDITALIC) */
+	int underline;		  /* Font underline(TRUE/FALSE) */
+	int underline_right;	  /* Extend right underline(TRUE/FALSE) */
+	int underline_left;	  /* Extend left underline(TRUE/FALSE) */
+	int background;		  /* Font Background Color(TRUE/FALSE) */
+	int transparency;		  /* Font transparency(0-255) */
+	int autofix;			  /* Font autofix(TRUE/FALSE) */
+	int precedingchar;      /* preceding character for autofix*/
+	int fixed_width;		  /* Font fixed width(TRUE/FALSE) */
+};
+
+
+/* global vars */
+BITMAP *default_bmp; //Draw Font on default BITMAP;
+static FT_Library ft_library;
+static int alfont_textmode = 0;
+static int alfont_inited = 0;
+
+const char *alfont_get_name(ALFONT_FONT *f) {
+	if (!f)
+		return "";
+
+	return ((FT_FaceRec *)(f->face))->family_name;
+}
+
+
+/*
+   JJS: These functions replace the standard Allegro blender.
+   Code is reverse-engineered from the alfont MSVC library.
+   The blender functions are based on the originals with small modifications
+   that enable correct drawing of anti-aliased fonts.
+*/
+
+/* original: _blender_trans15 in colblend.c */
+unsigned long __skiptranspixels_blender_trans15(unsigned long x, unsigned long y, unsigned long n) {
+	unsigned long result;
+
+	if ((y & 0xFFFF) == 0x7C1F)
+		return x;
+
+	if (n)
+		n = (n + 1) / 8;
+
+	x = ((x & 0xFFFF) | (x << 16)) & 0x3E07C1F;
+	y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F;
+
+	result = ((x - y) * n / 32 + y) & 0x3E07C1F;
+
+	return ((result & 0xFFFF) | (result >> 16));
+}
+
+/* original: _blender_trans16 in colblend.c */
+unsigned long __skiptranspixels_blender_trans16(unsigned long x, unsigned long y, unsigned long n) {
+	unsigned long result;
+
+	if ((y & 0xFFFF) == 0xF81F)
+		return x;
+
+	if (n)
+		n = (n + 1) / 8;
+
+	x = ((x & 0xFFFF) | (x << 16)) & 0x7E0F81F;
+	y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F;
+
+	result = ((x - y) * n / 32 + y) & 0x7E0F81F;
+
+	return ((result & 0xFFFF) | (result >> 16));
+}
+
+/* original: _blender_trans24 in colblend.c */
+unsigned long __preservedalpha_blender_trans24(unsigned long x, unsigned long y, unsigned long n) {
+	unsigned long res, g, alpha;
+
+	alpha = (y & 0xFF000000);
+
+	if ((y & 0xFFFFFF) == 0xFF00FF)
+		return ((x & 0xFFFFFF) | (n << 24));
+
+	if (n)
+		n++;
+
+	res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y;
+	y &= 0xFF00;
+	x &= 0xFF00;
+	g = (x - y) * n / 256 + y;
+
+	res &= 0xFF00FF;
+	g &= 0xFF00;
+
+	return res | g | alpha;
+}
+
+/* replaces set_trans_blender() */
+void set_preservedalpha_trans_blender(int r, int g, int b, int a) {
+	//set_blender_mode(__skiptranspixels_blender_trans15, __skiptranspixels_blender_trans16, __preservedalpha_blender_trans24, r, g, b, a);
+	set_blender_mode(kAlphaPreservedBlenderMode, r, g, b, a);
+}
+
+
+/* helpers */
+
+static void _alfont_reget_fixed_sizes(ALFONT_FONT *f) {
+	if (f->num_fixed_sizes < 0) {
+		/* scalable font */
+		f->fixed_sizes[0] = -1;
+	} else {
+		/* fixed */
+		int i;
+		for (i = 0; i < f->num_fixed_sizes; i++) {
+			f->fixed_sizes[i] = f->face->available_sizes[i].height;
+		}
+		/* set last one to -1 */
+		f->fixed_sizes[f->num_fixed_sizes] = -1;
+	}
+}
+
+
+static void _alfont_uncache_glyphs(ALFONT_FONT *f) {
+	if (f->cached_glyphs) {
+		int i;
+		for (i = 0; i < f->face->num_glyphs; i++) {
+			if (f->cached_glyphs[i].is_cached) {
+				f->cached_glyphs[i].is_cached = 0;
+				if (f->cached_glyphs[i].bmp) {
+					free(f->cached_glyphs[i].bmp);
+					f->cached_glyphs[i].bmp = NULL;
+				}
+				if (f->cached_glyphs[i].aabmp) {
+					free(f->cached_glyphs[i].aabmp);
+					f->cached_glyphs[i].aabmp = NULL;
+				}
+			}
+		}
+	}
+}
+
+
+static void _alfont_uncache_glyph_number(ALFONT_FONT *f, int glyph_number) {
+	if (f->cached_glyphs) {
+		if (f->cached_glyphs[glyph_number].is_cached) {
+			f->cached_glyphs[glyph_number].is_cached = 0;
+			if (f->cached_glyphs[glyph_number].bmp) {
+				free(f->cached_glyphs[glyph_number].bmp);
+				f->cached_glyphs[glyph_number].bmp = NULL;
+			}
+			if (f->cached_glyphs[glyph_number].aabmp) {
+				free(f->cached_glyphs[glyph_number].aabmp);
+				f->cached_glyphs[glyph_number].aabmp = NULL;
+			}
+		}
+	}
+}
+
+
+static void _alfont_delete_glyphs(ALFONT_FONT *f) {
+	_alfont_uncache_glyphs(f);
+	if (f->cached_glyphs) {
+		free(f->cached_glyphs);
+		f->cached_glyphs = NULL;
+	}
+}
+
+
+static void _alfont_cache_glyph(ALFONT_FONT *f, int glyph_number) {
+	/* if glyph not cached yet */
+	if (!f->cached_glyphs[glyph_number].is_cached) {
+		FT_Glyph new_glyph;
+		/* load the font glyph */
+		FT_Load_Glyph(f->face, glyph_number, FT_LOAD_DEFAULT);
+		FT_Get_Glyph(f->face->glyph, &new_glyph);
+
+		/* ok, this glyph is now cached */
+		f->cached_glyphs[glyph_number].is_cached = 1;
+		f->cached_glyphs[glyph_number].mono_available = 0;
+		f->cached_glyphs[glyph_number].aa_available = 0;
+
+		/* render the mono bmp */
+		{
+			FT_Bitmap *ft_bmp;
+			FT_Glyph glyph;
+			FT_BitmapGlyph bmp_glyph;
+
+			FT_Glyph_Copy(new_glyph, &glyph);
+
+			/* only render glyph if it is not already a bitmap */
+			if (glyph->format != ft_glyph_format_bitmap)
+				FT_Glyph_To_Bitmap(&glyph, ft_render_mode_mono, NULL, 1);
+
+			/* the FT rendered bitmap */
+			bmp_glyph = (FT_BitmapGlyph)glyph;
+			ft_bmp = &bmp_glyph->bitmap;
+
+			/* save only if the bitmap is really 1 bit */
+			if (ft_bmp->pixel_mode == ft_pixel_mode_mono) {
+				int memsize;
+
+				f->cached_glyphs[glyph_number].mono_available = 1;
+
+				/* set width, height, left, top */
+				f->cached_glyphs[glyph_number].width = ft_bmp->width;
+				f->cached_glyphs[glyph_number].height = ft_bmp->rows;
+				f->cached_glyphs[glyph_number].left = bmp_glyph->left;
+				f->cached_glyphs[glyph_number].top = bmp_glyph->top;
+
+				/* allocate bitmap */
+				memsize = ft_bmp->width * ft_bmp->rows * sizeof(unsigned char);
+				if (memsize > 0)
+					f->cached_glyphs[glyph_number].bmp = (byte *)malloc(memsize);
+				else
+					f->cached_glyphs[glyph_number].bmp = NULL;
+
+				/* monochrome drawing */
+				if (memsize > 0) {
+					unsigned char *outbmp_p = f->cached_glyphs[glyph_number].bmp;
+					unsigned char *bmp_p;
+					int bmp_x, bmp_y, bit;
+
+					/* copy the FT character bitmap to ours */
+					bmp_p = ft_bmp->buffer;
+					for (bmp_y = 0; bmp_y < (int)ft_bmp->rows; bmp_y++) {
+						unsigned char *next_bmp_p;
+						next_bmp_p = bmp_p + ft_bmp->pitch;
+						bit = 7;
+						for (bmp_x = 0; bmp_x < (int)ft_bmp->width; bmp_x++) {
+							*outbmp_p = *bmp_p & (1 << bit);
+							outbmp_p++;
+
+							if (bit == 0) {
+								bit = 7;
+								bmp_p++;
+							} else
+								bit--;
+						}
+						bmp_p = next_bmp_p;
+					}
+				}
+			}
+
+			FT_Done_Glyph(glyph);
+		}
+
+
+		/* render the aa bmp */
+		{
+			FT_Bitmap *ft_bmp;
+			FT_Glyph glyph;
+			FT_BitmapGlyph bmp_glyph;
+
+			FT_Glyph_Copy(new_glyph, &glyph);
+
+			/* only render glyph if it is not already a bitmap */
+			if (glyph->format != ft_glyph_format_bitmap)
+				FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, NULL, 1);
+
+			/* the FT rendered bitmap */
+			bmp_glyph = (FT_BitmapGlyph)glyph;
+			ft_bmp = &bmp_glyph->bitmap;
+
+			/* save only if the bitmap is really 8 bit */
+			if (ft_bmp->pixel_mode == ft_pixel_mode_grays) {
+				int memsize;
+
+				f->cached_glyphs[glyph_number].aa_available = 1;
+
+				/* set width, height, left, top */
+				f->cached_glyphs[glyph_number].aawidth = ft_bmp->width;
+				f->cached_glyphs[glyph_number].aaheight = ft_bmp->rows;
+				f->cached_glyphs[glyph_number].aaleft = bmp_glyph->left;
+				f->cached_glyphs[glyph_number].aatop = bmp_glyph->top;
+
+				/* allocate bitmap */
+				memsize = ft_bmp->width * ft_bmp->rows * sizeof(unsigned char);
+				if (memsize > 0)
+					f->cached_glyphs[glyph_number].aabmp = (byte *)malloc(memsize);
+				else
+					f->cached_glyphs[glyph_number].aabmp = NULL;
+
+				/* aa drawing */
+				if (memsize > 0) {
+					unsigned char *outbmp_p = f->cached_glyphs[glyph_number].aabmp;
+					unsigned char *bmp_p;
+					int bmp_y;
+					unsigned char mul = 256 / ft_bmp->num_grays;
+					/* we set it to 0 because it is faster to test for false */
+					if (mul == 1)
+						mul = 0;
+
+					/* copy the FT character bitmap to ours */
+					bmp_p = ft_bmp->buffer;
+					for (bmp_y = 0; bmp_y < (int)ft_bmp->rows; bmp_y++) {
+						unsigned char *next_bmp_p;
+						next_bmp_p = bmp_p + ft_bmp->pitch;
+						memcpy(outbmp_p, bmp_p, ft_bmp->width * sizeof(unsigned char));
+
+						/* we have to change our pixels if the numgrays is not 256 */
+						if (mul) {
+							unsigned char *p = outbmp_p;
+							unsigned char *p_end = p + ft_bmp->width;
+							for (; p < p_end; p++)
+								*p *= mul;
+						}
+
+						outbmp_p += ft_bmp->width;
+						bmp_p = next_bmp_p;
+					}
+				}
+			}
+
+			FT_Done_Glyph(glyph);
+		}
+
+		f->cached_glyphs[glyph_number].advancex = f->face->glyph->advance.x >> 6;
+		f->cached_glyphs[glyph_number].advancey = f->face->glyph->advance.y >> 6;
+
+		/* delete the glyph */
+		FT_Done_Glyph(new_glyph);
+	}
+}
+
+
+static void _alfont_new_cache_glyph(ALFONT_FONT *f) {
+	int i;
+
+	if (!f->cached_glyphs)
+		f->cached_glyphs = (_ALFONT_CACHED_GLYPH *)malloc(f->face->num_glyphs * sizeof(struct _ALFONT_CACHED_GLYPH));
+
+	for (i = 0; i < f->face->num_glyphs; i++) {
+		f->cached_glyphs[i].is_cached = 0;
+		f->cached_glyphs[i].bmp = NULL;
+		f->cached_glyphs[i].aabmp = NULL;
+	}
+}
+
+
+/* API */
+
+int alfont_set_font_size(ALFONT_FONT *f, int h) {
+	int error, test_h, direction;
+	int real_height = 0;
+	// AGS COMPAT HACK: always set ascender to the formal font height
+	int do_ascender_hack = TRUE; // TODO: make a func arg?
+	/* check the font doesn't already use that w and h */
+	if (h == f->face_h)
+		return ALFONT_OK;
+	else if (h <= 0)
+		return ALFONT_ERROR;
+
+	/* keep changing the size until the real size is not the one */
+	/* we want */
+	test_h = h;
+	direction = 0;
+	while (1) {
+		error = FT_Set_Pixel_Sizes(f->face, 0, test_h);
+		if (error)
+			break;
+
+		/* compare real height with asked height */
+		real_height = abs(f->face->size->metrics.ascender >> 6) + abs(f->face->size->metrics.descender >> 6);
+
+		// AGS COMPAT HACK: always choose the first result
+		break;
+
+		if (real_height == h) {
+			/* we found the wanted height */
+			break;
+		}
+
+		/* check the direction */
+		if (direction == 0) {
+			/* direction still not set */
+			if (real_height > h)
+				direction = -1;
 			else
-				delete winfont;
+				direction = 1;
+		}
+
+		/* check we didn't overpass it */
+		else if ((direction > 0) && (real_height > h)) {
+			/* decrease one and found */
+			test_h--;
+			FT_Set_Pixel_Sizes(f->face, 0, test_h);
+			break;
+		}
+
+		/* check we didn't surpass it */
+		else if ((direction < 0) && (real_height < h)) {
+			break;
+		}
+
+		test_h += direction;
+
+		/* check we arent at 0 */
+		if (test_h <= 0) {
+			error = TRUE;
+			break;
+		}
+	}
+
+	if (!error) {
+		_alfont_uncache_glyphs(f);
+		f->face_h = h;
+		f->real_face_h = real_height;
+		f->face_ascender = f->face->size->metrics.ascender >> 6;
+
+		// AGS COMPAT HACK: set ascender to the formal font height
+		if (do_ascender_hack) {
+			f->face_ascender = h;
+			f->real_face_h = h + abs(f->face->size->metrics.descender >> 6);
+		}
+
+		return ALFONT_OK;
+	} else {
+		FT_Set_Pixel_Sizes(f->face, 0, f->real_face_h);
+		return ALFONT_ERROR;
+	}
+}
+
+
+int alfont_get_font_height(ALFONT_FONT *f) {
+	return f->face_h;
+}
+
+/* Return font height based on ascender + descender summation */
+int alfont_get_font_real_height(ALFONT_FONT *f) {
+	return f->real_face_h;
+}
+
+void alfont_exit(void) {
+	if (alfont_inited) {
+		alfont_inited = 0;
+		FT_Done_FreeType(ft_library);
+		memset(&ft_library, 0, sizeof(ft_library));
+	}
+}
+
+
+int alfont_init(void) {
+	if (alfont_inited)
+		return 0;
+	else {
+		int error;
+		memset(&ft_library, 0, sizeof(ft_library));
+		error = FT_Init_FreeType(&ft_library);
+
+		if (!error)
+			alfont_inited = 1;
+
+		return error;
+	}
+}
+
+
+ALFONT_FONT *alfont_load_font(const char *filepathname) {
+	int error;
+
+	/* try to allocate the memory */
+	ALFONT_FONT *font = (ALFONT_FONT * )malloc(sizeof(ALFONT_FONT));
+
+	if (font == NULL)
+		return NULL;
+
+	/* clear the struct */
+	memset(font, 0, sizeof(ALFONT_FONT));
+	font->cached_glyphs = NULL;
+
+	/* we are loading from file, no mem buffer needed */
+	font->data = NULL;
+	font->data_size = 0;
+
+	/* load the font */
+	error = FT_New_Face(ft_library, filepathname, 0, &font->face);
+
+	if (error) {
+		free(font);
+		return NULL;
+	}
+
+	/* get if the font contains only fixed sizes */
+	if (!(font->face->face_flags & FT_FACE_FLAG_SCALABLE))
+		font->num_fixed_sizes = font->face->num_fixed_sizes;
+	else
+		font->num_fixed_sizes = -1;
+
+	_alfont_new_cache_glyph(font);
+
+	if (font->num_fixed_sizes < 0) {
+		font->fixed_sizes = (int *)malloc(sizeof(int));
+		_alfont_reget_fixed_sizes(font);
+
+		alfont_set_font_size(font, 8);
+	} else {
+		font->fixed_sizes = (int *)malloc(sizeof(int) * (font->num_fixed_sizes + 1));
+		_alfont_reget_fixed_sizes(font);
+
+		/* set as current size the first found fixed size */
+		alfont_set_font_size(font, font->fixed_sizes[0]);
+	}
+
+	alfont_set_char_extra_spacing(font, 0);
+
+	//Initial Font attribute
+	font->language = NULL;		   /* Initial Language */
+	font->type = 0;				   /* Initial Code Convert */
+	font->outline_top = 0;		   /* Initial Font top outline width */
+	font->outline_bottom = 0;	   /* Initial Font bottom outline width */
+	font->outline_left = 0;		   /* Initial Font left outline width */
+	font->outline_right = 0;	   /* Initial Font right outline width */
+	font->outline_color = 0;	   /* Initial Font outline color */
+	font->outline_hollow = FALSE;  /* Initial Font hollow(TRUE/FALSE) */
+	font->style = 0;			   /* Initial Font Style */
+	font->underline = FALSE;	   /* Initial Font underline(TRUE/FALSE) */
+	font->underline_right = FALSE; /* Initial Extend right underline(TRUE/FALSE) */
+	font->underline_left = FALSE;  /* Initial Extend left underline(TRUE/FALSE) */
+	font->background = FALSE;	   /* Initial Font Background Color(TRUE/FALSE) */
+	font->transparency = 255;	   /* Initial Font transparency(0-255) */
+	font->autofix = FALSE;		   /* Initial Font autofix(TRUE/FALSE) */
+	font->precedingchar = 0;	   /* Initial preceding character */
+
+	return font;
+}
+
+
+ALFONT_FONT *alfont_load_font_from_mem(const char *data, int data_len) {
+	int error;
+	char *new_data;
+
+	/* try to allocate the memory */
+	ALFONT_FONT *font = (ALFONT_FONT *)malloc(sizeof(ALFONT_FONT));
+	new_data = (char *)malloc(data_len);
+
+	if ((font == NULL) || (new_data == NULL)) {
+		if (font)
+			free(font);
+		if (new_data)
+			free(new_data);
+		return NULL;
+	}
+
+	/* clear the struct */
+	memset(font, 0, sizeof(ALFONT_FONT));
+	font->cached_glyphs = NULL;
+
+	/* copy user data to internal buffer */
+	font->data = new_data;
+	font->data_size = data_len;
+	memcpy((void *)font->data, (void *)data, data_len);
+
+	/* load the font */
+	error = FT_New_Memory_Face(ft_library, (const FT_Byte *)font->data, font->data_size, 0, &font->face);
+
+	if (error) {
+		free(font->data);
+		free(font);
+		return NULL;
+	}
+
+	/* get if the font contains only fixed sizes */
+	if (!(font->face->face_flags & FT_FACE_FLAG_SCALABLE))
+		font->num_fixed_sizes = font->face->num_fixed_sizes;
+	else
+		font->num_fixed_sizes = -1;
+
+	_alfont_new_cache_glyph(font);
+
+	if (font->num_fixed_sizes < 0) {
+		font->fixed_sizes = (int *)malloc(sizeof(int));
+		_alfont_reget_fixed_sizes(font);
+
+		alfont_set_font_size(font, 8);
+	} else {
+		font->fixed_sizes = (int *)malloc(sizeof(int) * (font->num_fixed_sizes + 1));
+		_alfont_reget_fixed_sizes(font);
+
+		/* set as current size the first found fixed size */
+		alfont_set_font_size(font, font->fixed_sizes[0]);
+	}
+
+	alfont_set_char_extra_spacing(font, 0);
+
+	//Initial Font attribute
+	font->language = NULL;		   /* Initial Language */
+	font->type = 0;				   /* Initial Code Convert */
+	font->outline_top = 0;		   /* Initial Font top outline width */
+	font->outline_bottom = 0;	   /* Initial Font bottom outline width */
+	font->outline_left = 0;		   /* Initial Font left outline width */
+	font->outline_right = 0;	   /* Initial Font right outline width */
+	font->outline_color = 0;	   /* Initial Font outline color */
+	font->outline_hollow = FALSE;  /* Initial Font hollow(TRUE/FALSE) */
+	font->style = 0;			   /* Initial Font Style */
+	font->underline = FALSE;	   /* Initial Font underline(TRUE/FALSE) */
+	font->underline_right = FALSE; /* Initial Extend right underline(TRUE/FALSE) */
+	font->underline_left = FALSE;  /* Initial Extend left underline(TRUE/FALSE) */
+	font->background = FALSE;	   /* Initial Font Background Color(TRUE/FALSE) */
+	font->transparency = 255;	   /* Initial Font transparency(0-255) */
+	font->autofix = FALSE;		   /* Initial Font autofix(TRUE/FALSE) */
+	font->precedingchar = 0;	   /* Initial preceding character */
+
+	return font;
+}
+
+
+int alfont_text_mode(int mode) {
+	int old_mode = alfont_textmode;
+	alfont_textmode = mode;
+	return old_mode;
+}
+
+
+void alfont_destroy_font(ALFONT_FONT *f) {
+	if (f == NULL)
+		return;
+
+	/* delete old glyphs */
+	_alfont_delete_glyphs(f);
+
+	/* delete the face */
+	FT_Done_Face(f->face);
+
+	if (f->fixed_sizes)
+		free(f->fixed_sizes);
+
+	/* deallocate the data */
+	if (f->data)
+		free(f->data);
+
+	/* deallocate the language string*/
+	if (f->language)
+		free(f->language);
+
+	free(f);
+}
+
+
+void alfont_textout_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {
+	alfont_textout_aa_ex(bmp, f, s, x, y, color, alfont_textmode);
+}
+
+void alfont_textout_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int backg) {
+	char *lpszW;
+	char *lpszW_tmp;
+	int x_tmp;
+	int max_advancex = 0;
+	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int character;
+	int alpha_table[256];
+	int last_glyph_index;
+	int first_x = 0, final_x = 0, final_y = 0;
+	int curr_uformat = 0;
+	int first_flag = TRUE; //First Char flag
+	BITMAP *masked_bmp = nullptr; //the masked bmp used by Font hollow
+
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (s == NULL) {
+		return;
+	}
+
+	nLen = strlen(s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the s string
+	//If find the cutted character, store it from the converted s string and remove it from the original s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+	if (f->type == 1) {
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	/* is it under or over or too far to the right of the clipping rect then
+	   we can assume the string is clipped */
+	if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr))
+		return;
+
+	//build transparency
+	if (f->transparency != 255) {
+		if (bitmap_color_depth(bmp) > 8) {
+			drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+			set_preservedalpha_trans_blender(0, 0, 0, f->transparency);
+		}
+	} else {
+		drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+	}
+
+	/* if we are doing opaque mode, draw a rect and init our table*/
+	if (backg >= 0) {
+		int i, r, g, b, br, bg, bb, ir, ig, ib;
+		int blendr, blendg, blendb;
+
+		if (f->background == TRUE) {
+			rectfill(bmp, x, y, x + alfont_text_length(f, s_pointer) - 1, y + f->face_h - 1, backg);
+		}
+
+		/* get the color rgb */
+		r = getr(color); g = getg(color); b = getb(color);
+
+		/* get the background rgb */
+		br = getr(backg); bg = getg(backg); bb = getb(backg);
+
+		/* get increments */
+		ir = (r == br) ? 0 : (r + 1) - br;
+		ig = (g == bg) ? 0 : (g + 1) - bg;
+		ib = (b == bb) ? 0 : (b + 1) - bb;
+
+		blendr = br << 8;
+		blendg = bg << 8;
+		blendb = bb << 8;
+
+		/* blend both values and make our alpha table */
+		for (i = 0; i < 256; i++) {
+			alpha_table[i] = makecol(blendr >> 8, blendg >> 8, blendb >> 8);
+			blendr += ir;
+			blendg += ig;
+			blendb += ib;
+		}
+	}
+
+	/* draw char by char (using allegro unicode funcs) */
+	acquire_bitmap(bmp);
+	last_glyph_index = 0;
+
+	if (f->fixed_width == TRUE) {
+		lpszW_tmp = lpszW;
+		x_tmp = x;
+		max_advancex = 0;
+
+		_alfont_uncache_glyphs(f);
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp), character = ugetxc((const char **)&lpszW_tmp)) {
+#else
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp)) {
+#endif
+			int glyph_index_tmp;
+			struct _ALFONT_CACHED_GLYPH cglyph_tmp;
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+			if (f->type != 2) {
+				lpszW_tmp--;
+			}
+#endif
+
+			/* if left side of char farther than right side of clipping, we are done */
+			if (x_tmp > bmp->cr)
+				break;
+
+			/* get the character out of the font */
+			if (f->face->charmap)
+				glyph_index_tmp = FT_Get_Char_Index(f->face, character);
+			else
+				glyph_index_tmp = character;
+
+			/* cache the glyph */
+			_alfont_cache_glyph(f, glyph_index_tmp);
+			cglyph_tmp = f->cached_glyphs[glyph_index_tmp];
+			if (max_advancex < f->cached_glyphs[glyph_index_tmp].advancex)
+				max_advancex = f->cached_glyphs[glyph_index_tmp].advancex;
+
+			/* advance */
+			if (cglyph_tmp.advancex)
+				x_tmp += cglyph_tmp.advancex + f->ch_spacing;
+
+		}
+		}
+
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW), character = ugetxc((const char **)&lpszW)) {
+#else
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW)) {
+#endif
+		int real_x, real_y, glyph_index;
+		struct _ALFONT_CACHED_GLYPH cglyph;
+
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+		if (f->type != 2) {
+			lpszW--;
+		}
+#endif
+
+		/* if left side of char farther than right side of clipping, we are done */
+		if (x > bmp->cr)
+			break;
+
+		/* get the character out of the font */
+		if (f->face->charmap)
+			glyph_index = FT_Get_Char_Index(f->face, character);
+		else
+			glyph_index = character;
+
+		/* cache the glyph */
+		_alfont_cache_glyph(f, glyph_index);
+		if (f->fixed_width == TRUE)
+			f->cached_glyphs[glyph_index].advancex = max_advancex;
+
+		cglyph = f->cached_glyphs[glyph_index];
+
+		/* calculate drawing coords */
+		real_x = x + cglyph.aaleft;
+		real_y = (y - cglyph.aatop) + f->face_ascender;
+
+		/* apply kerning */
+		/*if (last_glyph_index) {
+			FT_Vector v;
+			FT_Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
+			real_x += v.x >> 6;
+			real_y += v.y >> 6;
+		}*/
+		last_glyph_index = glyph_index;
+
+		/* draw only if exists */
+		if ((cglyph.aa_available) && (cglyph.aabmp)) {
+
+			int bmp_x, bmp_y, outline_w;
+			unsigned char *bmp_p = cglyph.aabmp;
+			const int max_bmp_x = cglyph.aawidth + real_x;
+			const int max_bmp_y = cglyph.aaheight + real_y;
+
+			if (first_flag == TRUE) {
+				first_x = max_bmp_x;
+			}
+
+			/* if in opaque mode */
+			if (backg >= 0) {
+				if (f->outline_hollow == TRUE) { //Set masked region
+					//cancel transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+						}
+					}
+					if (f->style == 1) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else if (f->style == 2) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else if (f->style == 3) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					}
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							if (*bmp_p++) {
+								if (first_x > bmp_x) first_x = bmp_x;
+								if (final_x < bmp_x) final_x = bmp_x;
+								if (final_y < bmp_y) final_y = bmp_y;
+								if (f->style == 1) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+								} else if (f->style == 2) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+										if (final_x < (bmp_x)) final_x = bmp_x;
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+										if (first_x > (bmp_x)) first_x = bmp_x;
+									}
+									putpixel(masked_bmp, bmp_x + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + 1, bmp_y));
+									putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+								} else if (f->style == 3) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y));
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+								} else {
+									putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+								}
+							}
+						}
+					}
+					//restore transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+						}
+					}
+					bmp_p = cglyph.aabmp; //repointer to Font bmp pointer and draw outline
+				}
+
+				if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							const int alpha = *bmp_p++;
+							if (alpha) {
+								if (f->outline_right > 0) {
+									for (outline_w = 0; outline_w < f->outline_right; outline_w++) {
+										if (bmp_x + (outline_w + 1) <= max_bmp_x) {
+											if (f->style == 1) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2);
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2), bmp_y, f->outline_color);
+											} else if (f->style == 2) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + 1)) final_x = bmp_x + (outline_w + 1) + 1;
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + 1, bmp_y, f->outline_color);
+											} else if (f->style == 3) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1;
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, f->outline_color);
+											} else {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1))) final_x = bmp_x + (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1), bmp_y, f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_bottom > 0) {
+									for (outline_w = 0; outline_w < f->outline_bottom; outline_w++) {
+										if (bmp_y + (outline_w + 1) <= max_bmp_y) {
+											if (f->style == 1) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+											} else if (f->style == 2) {
+												putpixel(bmp, bmp_x + 1, bmp_y + (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+											} else if (f->style == 3) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y + (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+											} else {
+												putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_left > 0) {
+									for (outline_w = 0; outline_w < f->outline_left; outline_w++) {
+										if (bmp_x - (outline_w + 1) >= real_x - 1) {
+											if (f->style == 1) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+											} else if (f->style == 2) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+											} else if (f->style == 3) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+											} else {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_top > 0) {
+									for (outline_w = 0; outline_w < f->outline_top; outline_w++) {
+										if (bmp_y - (outline_w + 1) >= real_y - 1) {
+											if (f->style == 1) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+											} else if (f->style == 2) {
+												putpixel(bmp, bmp_x + 1, bmp_y - (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+											} else if (f->style == 3) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y - (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+											} else {
+												putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				if (f->outline_hollow == FALSE) { //check if it will restore the masked region
+					bmp_p = cglyph.aabmp; //repointer to Font bmp pointer
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							const int alpha = *bmp_p++;
+
+							if (alpha) {
+								if (first_x > bmp_x) first_x = bmp_x;
+								if (final_x < bmp_x) final_x = bmp_x;
+								if (final_y < bmp_y) final_y = bmp_y;
+								if (f->style == 1) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, alpha_table[alpha]);
+								} else if (f->style == 2) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+										if (final_x < (bmp_x)) final_x = bmp_x;
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+										if (first_x > (bmp_x)) first_x = bmp_x;
+									}
+									putpixel(bmp, bmp_x + 1, bmp_y, alpha_table[alpha]);
+									putpixel(bmp, bmp_x, bmp_y, alpha_table[alpha]);
+								} else if (f->style == 3) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, alpha_table[alpha]);
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, alpha_table[alpha]);
+								} else {
+									putpixel(bmp, bmp_x, bmp_y, alpha_table[alpha]);
+								}
+							}
+						}
+					}
+				} else { //restore original pic
+					//cancel transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+						}
+					}
+					if (f->style == 1) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else if (f->style == 2) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else if (f->style == 3) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					}
+					//restore transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+						}
+					}
+				}
+			}
+
+			/* if in transparent mode */
+			else {
+				if (f->outline_hollow == TRUE) { //set the masked region
+					//cancel transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+						}
+					}
+					if (f->style == 1) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else if (f->style == 2) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else if (f->style == 3) {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					} else {
+						masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x - real_x, max_bmp_y - real_y);
+						clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					}
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							if (*bmp_p++) {
+								if (first_x > bmp_x) first_x = bmp_x;
+								if (final_x < bmp_x) final_x = bmp_x;
+								if (final_y < bmp_y) final_y = bmp_y;
+								if (f->style == 1) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+								} else if (f->style == 2) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+										if (final_x < (bmp_x)) final_x = bmp_x;
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+										if (first_x > (bmp_x)) first_x = bmp_x;
+									}
+									putpixel(masked_bmp, bmp_x + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + 1, bmp_y));
+									putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+								} else if (f->style == 3) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y));
+									putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+								} else {
+									putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+								}
+							}
+						}
+					}
+					//restore transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+						}
+					}
+					bmp_p = cglyph.aabmp; //repointer to Font bmp pointer and draw outline
+				}
+
+				if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							const int alpha = *bmp_p++;
+							if (alpha) {
+								if (f->outline_right > 0) {
+									for (outline_w = 0; outline_w < f->outline_right; outline_w++) {
+										if (bmp_x + (outline_w + 1) <= max_bmp_x) {
+											if (f->style == 1) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2);
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2), bmp_y, f->outline_color);
+											} else if (f->style == 2) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + 1)) final_x = bmp_x + (outline_w + 1) + 1;
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + 1, bmp_y, f->outline_color);
+											} else if (f->style == 3) {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1;
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, f->outline_color);
+											} else {
+												if (f->underline_right == TRUE) {
+													if (final_x < (bmp_x + (outline_w + 1))) final_x = bmp_x + (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + (outline_w + 1), bmp_y, f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_bottom > 0) {
+									for (outline_w = 0; outline_w < f->outline_bottom; outline_w++) {
+										if (bmp_y + (outline_w + 1) <= max_bmp_y) {
+											if (f->style == 1) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+											} else if (f->style == 2) {
+												putpixel(bmp, bmp_x + 1, bmp_y + (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+											} else if (f->style == 3) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y + (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+											} else {
+												putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_left > 0) {
+									for (outline_w = 0; outline_w < f->outline_left; outline_w++) {
+										if (bmp_x - (outline_w + 1) >= real_x - 1) {
+											if (f->style == 1) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+											} else if (f->style == 2) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+											} else if (f->style == 3) {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+											} else {
+												if (f->underline_left == TRUE) {
+													if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+												}
+												putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+											}
+										}
+									}
+								}
+								if (f->outline_top > 0) {
+									for (outline_w = 0; outline_w < f->outline_top; outline_w++) {
+										if (bmp_y - (outline_w + 1) >= real_y - 1) {
+											if (f->style == 1) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+											} else if (f->style == 2) {
+												putpixel(bmp, bmp_x + 1, bmp_y - (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+											} else if (f->style == 3) {
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y - (outline_w + 1), f->outline_color);
+												putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+											} else {
+												putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+				if (f->outline_hollow == FALSE) { //check if it will restore the masked region
+					bmp_p = cglyph.aabmp; //repointer to Font bmp pointer
+					for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+						for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+							const int alpha = *bmp_p++;
+
+							if (alpha) {
+								if (alpha >= 255)
+									solid_mode();
+								else {
+									drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+									set_preservedalpha_trans_blender(0, 0, 0, alpha);
+								}
+								if (first_x > bmp_x) first_x = bmp_x;
+								if (final_x < bmp_x) final_x = bmp_x;
+								if (final_y < bmp_y) final_y = bmp_y;
+								if (f->style == 1) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, color);
+								} else if (f->style == 2) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+										if (final_x < (bmp_x)) final_x = bmp_x;
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+										if (first_x > (bmp_x)) first_x = bmp_x;
+									}
+									putpixel(bmp, bmp_x + 1, bmp_y, color);
+									putpixel(bmp, bmp_x, bmp_y, color);
+								} else if (f->style == 3) {
+									if (f->underline_right == TRUE) {
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									if (f->underline_left == TRUE) {
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+										if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+									}
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, color);
+									putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, color);
+								} else {
+									putpixel(bmp, bmp_x, bmp_y, color);
+								}
+							}
+						}
+					}
+				} else { //restore original pic
+					//cancel transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+						}
+					}
+					if (f->style == 1) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else if (f->style == 2) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else if (f->style == 3) {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					} else {
+						masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x - real_x, max_bmp_y - real_y);
+						destroy_bitmap(masked_bmp);
+					}
+					//restore transparency
+					if (f->transparency != 255) {
+						if (bitmap_color_depth(bmp) > 8) {
+							drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+						}
+					}
+				}
+			}
+		}
+
+		/* advance */
+		if (cglyph.advancex)
+			x += cglyph.advancex + f->ch_spacing;
+		if (cglyph.advancey)
+			y += cglyph.advancey + f->ch_spacing;
+
+		first_flag = FALSE; //set first char flag is FALSE
+	}
+	//draw underline
+	if ((f->underline) == TRUE) {
+		if ((final_y + ((f->real_face_h) >> 5)) > 5) {
+			if (f->outline_hollow == TRUE) { //set the masked region for underline
+				int bmp_x, bmp_y;
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE,extend right underline
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x + f->ch_spacing - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + ((f->real_face_h) >> 5); bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x + f->ch_spacing; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				} else { //If the underline_right is not TRUE,just draw underline
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + ((f->real_face_h) >> 5); bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+			//Draw outline
+			if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+				if (f->outline_top > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y - 1, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y - 1, final_x, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+				if (f->outline_bottom > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5) + 1, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y, final_x, final_y + ((f->real_face_h) >> 5) + 1, f->outline_color);
+					}
+				}
+				if (f->outline_left > 0) {
+					if (f->underline_left == FALSE) {
+						rectfill(bmp, first_x - 1, final_y, final_x, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+				if (f->outline_right > 0) {
+					if (f->underline_right == FALSE) {
+						rectfill(bmp, first_x, final_y, final_x + 1, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+			}
+			if (f->outline_hollow == FALSE) { //check if it is the masked region for outline
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5), color);
+				} else { //If the underline_right is FALSE
+					rectfill(bmp, first_x, final_y, final_x, final_y + ((f->real_face_h) >> 5), color);
+				}
+			} else {
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x + f->ch_spacing - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				} else { //If the underline_right is FALSE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+		} else {
+			if (f->outline_hollow == TRUE) { //set the masked region for underline
+				int bmp_x, bmp_y;
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x + f->ch_spacing - first_x + 1, final_y + 5 - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + 5; bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x + f->ch_spacing; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				} else { //If the underline_right is FALSE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x - first_x + 1, final_y + 5 - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + 5; bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+			//Draw outline
+			if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+				if (f->outline_top > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y - 1, final_x + f->ch_spacing, final_y + 5, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y - 1, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_bottom > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + 5, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_left > 0) {
+					if (f->underline_left == FALSE) {
+						rectfill(bmp, first_x - 1, final_y, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_right > 0) {
+					if (f->underline_right == FALSE) {
+						rectfill(bmp, first_x, final_y, final_x + 1, final_y + 5, f->outline_color);
+					}
+				}
+			}
+			if (f->outline_hollow == FALSE) { //check if it is the masked region for outline
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + 5, color);
+				} else { //If the underline_right is FALSE
+					rectfill(bmp, first_x, final_y, final_x, final_y + 5, color);
+				}
+			} else {
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x + f->ch_spacing - first_x + 1, final_y + 5 - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				} else { //If the underline_right is FALSE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x - first_x + 1, final_y + 5 - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+		}
+	}
+
+	release_bitmap(bmp);
+
+	/* reset blender */
+	if (backg < 0)
+		solid_mode();
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW_pointer)
+			free(lpszW_pointer);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	}
+
+
+void alfont_textout(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color) {
+	alfont_textout_ex(bmp, f, s, x, y, color, alfont_textmode);
+}
+
+
+void alfont_textout_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color, int backg) {
+	char *lpszW;
+	char *lpszW_tmp;
+	int x_tmp;
+	int max_advancex = 0;
+	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int character, last_glyph_index;
+	int first_x = 0, final_x = 0, final_y = 0;
+	int curr_uformat = 0;
+	int first_flag = TRUE; //First Char flag
+	BITMAP *masked_bmp = nullptr; //the masked bmp used by Font hollow
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (s == NULL) {
+		return;
+	}
+
+	nLen = strlen(s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the s string
+	//If find the cutted character, store it from the converted s string and remove it from the original s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	/* is it under or over or too far to the right of the clipping rect then
+	   we can assume the string is clipped */
+	if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr))
+		return;
+
+	//build transparency
+	if (f->transparency != 255) {
+		if (bitmap_color_depth(bmp) > 8) {
+			drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+			set_preservedalpha_trans_blender(0, 0, 0, f->transparency);
+		}
+	} else {
+		drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+	}
+
+	/* if we are doing opaque mode, draw a rect */
+	if (backg >= 0) {
+		if (f->background == TRUE) {
+			rectfill(bmp, x, y, x + alfont_text_length(f, s_pointer) - 1, y + f->face_h - 1, backg);
+		}
+	}
+
+	/* draw char by char (using allegro unicode funcs) */
+	acquire_bitmap(bmp);
+	last_glyph_index = 0;
+
+
+	if (f->fixed_width == TRUE) {
+		lpszW_tmp = lpszW;
+		x_tmp = x;
+		max_advancex = 0;
+
+		_alfont_uncache_glyphs(f);
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp), character = ugetxc((const char **)&lpszW_tmp)) {
+#else
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp)) {
+#endif
+			int glyph_index_tmp;
+			struct _ALFONT_CACHED_GLYPH cglyph_tmp;
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+			if (f->type != 2) {
+				lpszW_tmp--;
+			}
+#endif
+
+			/* if left side of char farther than right side of clipping, we are done */
+			if (x_tmp > bmp->cr)
+				break;
+
+			/* get the character out of the font */
+			if (f->face->charmap)
+				glyph_index_tmp = FT_Get_Char_Index(f->face, character);
+			else
+				glyph_index_tmp = character;
+
+			/* cache the glyph */
+			_alfont_cache_glyph(f, glyph_index_tmp);
+			cglyph_tmp = f->cached_glyphs[glyph_index_tmp];
+			if (max_advancex < f->cached_glyphs[glyph_index_tmp].advancex)
+				max_advancex = f->cached_glyphs[glyph_index_tmp].advancex;
+
+			/* advance */
+			if (cglyph_tmp.advancex)
+				x_tmp += cglyph_tmp.advancex + f->ch_spacing;
+
+		}
+		}
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW), character = ugetxc((const char **)&lpszW)) {
+#else
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW)) {
+#endif
+		int real_x, real_y, glyph_index;
+		struct _ALFONT_CACHED_GLYPH cglyph;
+
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+		if (f->type != 2) {
+			lpszW--;
+		}
+#endif
+
+		/* if left side of char farther than right side of clipping, we are done */
+		if (x > bmp->cr)
+			break;
+
+		/* get the character out of the font */
+		if (f->face->charmap)
+			glyph_index = FT_Get_Char_Index(f->face, character);
+		else
+			glyph_index = character;
+
+		/* cache the glyph */
+		_alfont_cache_glyph(f, glyph_index);
+		if (f->fixed_width == TRUE)
+			f->cached_glyphs[glyph_index].advancex = max_advancex;
+
+		cglyph = f->cached_glyphs[glyph_index];
+
+		/* calculate drawing coords */
+		real_x = x + cglyph.left;
+		real_y = (y - cglyph.top) + f->face_ascender;
+
+		/* apply kerning */
+		/*if (last_glyph_index) {
+			FT_Vector v;
+			FT_Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
+			real_x += v.x >> 6;
+			real_y += v.y >> 6;
+		}*/
+		last_glyph_index = glyph_index;
+
+		/* draw only if exists */
+		if ((cglyph.mono_available) && (cglyph.bmp)) {
+			unsigned char *bmp_p = cglyph.bmp;
+			/* monochrome drawing */
+			int bmp_x, bmp_y, outline_w;
+
+			/* copy the character bitmap to our allegro one */
+			const int max_bmp_x = cglyph.width + real_x;
+			const int max_bmp_y = cglyph.height + real_y;
+
+			if (first_flag == TRUE) {
+				first_x = max_bmp_x;
+			}
+
+			if (f->outline_hollow == TRUE) { //Set masked region
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->style == 1) {
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+				} else if (f->style == 2) {
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+				} else if (f->style == 3) {
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+				} else {
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), max_bmp_x - real_x, max_bmp_y - real_y);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+				}
+				for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+					for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+						if (*bmp_p++) {
+							if (first_x > bmp_x) first_x = bmp_x;
+							if (final_x < bmp_x) final_x = bmp_x;
+							if (final_y < bmp_y) final_y = bmp_y;
+							if (f->style == 1) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+							} else if (f->style == 2) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+									if (final_x < (bmp_x)) final_x = bmp_x;
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+									if (first_x > (bmp_x)) first_x = bmp_x;
+								}
+								putpixel(masked_bmp, bmp_x + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + 1, bmp_y));
+								putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+							} else if (f->style == 3) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1 - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y));
+								putpixel(masked_bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - real_x, bmp_y - real_y, getpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y));
+							} else {
+								putpixel(masked_bmp, bmp_x - real_x, bmp_y - real_y, getpixel(bmp, bmp_x, bmp_y));
+							}
+						}
+					}
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+				bmp_p = cglyph.bmp; //repointer to Font bmp pointer and draw outline
+			}
+
+			if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+				for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+					for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+						if (*bmp_p++) {
+							if (f->outline_right > 0) {
+								for (outline_w = 0; outline_w < f->outline_right; outline_w++) {
+									if (bmp_x + (outline_w + 1) <= max_bmp_x) {
+										if (f->style == 1) {
+											if (f->underline_right == TRUE) {
+												if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2);
+											}
+											putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2), bmp_y, f->outline_color);
+										} else if (f->style == 2) {
+											if (f->underline_right == TRUE) {
+												if (final_x < (bmp_x + (outline_w + 1) + 1)) final_x = bmp_x + (outline_w + 1) + 1;
+											}
+											putpixel(bmp, bmp_x + (outline_w + 1) + 1, bmp_y, f->outline_color);
+										} else if (f->style == 3) {
+											if (f->underline_right == TRUE) {
+												if (final_x < (bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1;
+											}
+											putpixel(bmp, bmp_x + (outline_w + 1) + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, f->outline_color);
+										} else {
+											if (f->underline_right == TRUE) {
+												if (final_x < (bmp_x + (outline_w + 1))) final_x = bmp_x + (outline_w + 1);
+											}
+											putpixel(bmp, bmp_x + (outline_w + 1), bmp_y, f->outline_color);
+										}
+									}
+								}
+							}
+							if (f->outline_bottom > 0) {
+								for (outline_w = 0; outline_w < f->outline_bottom; outline_w++) {
+									if (bmp_y + (outline_w + 1) <= max_bmp_y) {
+										if (f->style == 1) {
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+										} else if (f->style == 2) {
+											putpixel(bmp, bmp_x + 1, bmp_y + (outline_w + 1), f->outline_color);
+											putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+										} else if (f->style == 3) {
+
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y + (outline_w + 1), f->outline_color);
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y + (outline_w + 1), f->outline_color);
+										} else {
+											putpixel(bmp, bmp_x, bmp_y + (outline_w + 1), f->outline_color);
+										}
+									}
+								}
+							}
+							if (f->outline_left > 0) {
+								for (outline_w = 0; outline_w < f->outline_left; outline_w++) {
+									if (bmp_x - (outline_w + 1) >= real_x - 1) {
+										if (f->style == 1) {
+											if (f->underline_left == TRUE) {
+												if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+											}
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+										} else if (f->style == 2) {
+											if (f->underline_left == TRUE) {
+												if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+											}
+											putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+										} else if (f->style == 3) {
+											if (f->underline_left == TRUE) {
+												if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1);
+											}
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) - (outline_w + 1), bmp_y, f->outline_color);
+										} else {
+											if (f->underline_left == TRUE) {
+												if (first_x > (bmp_x - (outline_w + 1))) first_x = bmp_x - (outline_w + 1);
+											}
+											putpixel(bmp, bmp_x - (outline_w + 1), bmp_y, f->outline_color);
+										}
+									}
+								}
+							}
+							if (f->outline_top > 0) {
+								for (outline_w = 0; outline_w < f->outline_top; outline_w++) {
+									if (bmp_y - (outline_w + 1) >= real_y - 1) {
+										if (f->style == 1) {
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+										} else if (f->style == 2) {
+											putpixel(bmp, bmp_x + 1, bmp_y - (outline_w + 1), f->outline_color);
+											putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+										} else if (f->style == 3) {
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y - (outline_w + 1), f->outline_color);
+											putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y - (outline_w + 1), f->outline_color);
+										} else {
+											putpixel(bmp, bmp_x, bmp_y - (outline_w + 1), f->outline_color);
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			if (f->outline_hollow == FALSE) { //check if it will restore the masked region
+				bmp_p = cglyph.bmp; //repointer to Font bmp pointer
+				for (bmp_y = real_y; bmp_y < max_bmp_y; bmp_y++) {
+					for (bmp_x = real_x; bmp_x < max_bmp_x; bmp_x++) {
+						if (*bmp_p++) {
+							if (first_x > bmp_x) first_x = bmp_x;
+							if (final_x < bmp_x) final_x = bmp_x;
+							if (final_y < bmp_y) final_y = bmp_y;
+							if (f->style == 1) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, color);
+							} else if (f->style == 2) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + 1)) final_x = bmp_x + 1;
+									if (final_x < (bmp_x)) final_x = bmp_x;
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + 1)) first_x = bmp_x + 1;
+									if (first_x > (bmp_x)) first_x = bmp_x;
+								}
+								putpixel(bmp, bmp_x + 1, bmp_y, color);
+								putpixel(bmp, bmp_x, bmp_y, color);
+							} else if (f->style == 3) {
+								if (f->underline_right == TRUE) {
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+									if (final_x < (bmp_x + ((max_bmp_y - bmp_y) / 2))) final_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								if (f->underline_left == TRUE) {
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2) + 1)) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2) + 1;
+									if (first_x > (bmp_x + ((max_bmp_y - bmp_y) / 2))) first_x = bmp_x + ((max_bmp_y - bmp_y) / 2);
+								}
+								putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2) + 1, bmp_y, color);
+								putpixel(bmp, bmp_x + ((max_bmp_y - bmp_y) / 2), bmp_y, color);
+							} else {
+								putpixel(bmp, bmp_x, bmp_y, color);
+							}
+						}
+					}
+				}
+			} else { //restore original pic
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->style == 1) {
+					masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) - real_x, max_bmp_y - real_y);
+					destroy_bitmap(masked_bmp);
+				} else if (f->style == 2) {
+					masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + 1 - real_x, max_bmp_y - real_y);
+					destroy_bitmap(masked_bmp);
+				} else if (f->style == 3) {
+					masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x + ((max_bmp_y - real_y) / 2) + 1 - real_x, max_bmp_y - real_y);
+					destroy_bitmap(masked_bmp);
+				} else {
+					masked_blit(masked_bmp, bmp, 0, 0, real_x, real_y, max_bmp_x - real_x, max_bmp_y - real_y);
+					destroy_bitmap(masked_bmp);
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+		}
+
+		/* advance */
+		if (cglyph.advancex)
+			x += cglyph.advancex + f->ch_spacing;
+		if (cglyph.advancey)
+			y += cglyph.advancey + f->ch_spacing;
+
+		first_flag = FALSE; //set first char flag is FALSE
+	}
+
+	//draw underline
+	if ((f->underline) == TRUE) {
+		if ((final_y + ((f->real_face_h) >> 5)) > 5) {
+			if (f->outline_hollow == TRUE) { //set the masked region for underline
+				int bmp_x, bmp_y;
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x + f->ch_spacing - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + ((f->real_face_h) >> 5); bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x + f->ch_spacing; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				} else { //If the underline_right is FALSE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + ((f->real_face_h) >> 5); bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+			//Draw outline
+			if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+				if (f->outline_top > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y - 1, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y - 1, final_x, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+				if (f->outline_bottom > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5) + 1, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y, final_x, final_y + ((f->real_face_h) >> 5) + 1, f->outline_color);
+					}
+				}
+				if (f->outline_left > 0) {
+					if (f->underline_left == FALSE) {
+						rectfill(bmp, first_x - 1, final_y, final_x, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+				if (f->outline_right > 0) {
+					if (f->underline_right == FALSE) {
+						rectfill(bmp, first_x, final_y, final_x + 1, final_y + ((f->real_face_h) >> 5), f->outline_color);
+					}
+				}
+			}
+			if (f->outline_hollow == FALSE) { //check if it is the masked region for outline
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + ((f->real_face_h) >> 5), color);
+				} else { //If the underline_right is FALSE
+					rectfill(bmp, first_x, final_y, final_x, final_y + ((f->real_face_h) >> 5), color);
+				}
+			} else {
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x + f->ch_spacing - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				} else { //If the underline_right is FALSE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x - first_x + 1, final_y + ((f->real_face_h) >> 5) - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+		} else {
+			if (f->outline_hollow == TRUE) { //set the masked region for underline
+				int bmp_x, bmp_y;
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x + f->ch_spacing - first_x + 1, final_y + 5 - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + 5; bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x + f->ch_spacing; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				} else { //If the underline_right is FALSE
+					masked_bmp = create_bitmap_ex(bitmap_color_depth(bmp), final_x - first_x + 1, final_y + 5 - final_y + 1);
+					clear_to_color(masked_bmp, bitmap_mask_color(bmp));
+					for (bmp_y = final_y; bmp_y <= final_y + 5; bmp_y++) {
+						for (bmp_x = first_x; bmp_x <= final_x; bmp_x++) {
+							putpixel(masked_bmp, bmp_x - first_x, bmp_y - final_y, getpixel(bmp, bmp_x, bmp_y));
+						}
+					}
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+			//Draw outline
+			if ((f->outline_top > 0) || (f->outline_bottom > 0) || (f->outline_left > 0) || (f->outline_right > 0)) {
+				if (f->outline_top > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y - 1, final_x + f->ch_spacing, final_y + 5, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y - 1, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_bottom > 0) {
+					if (f->underline_right == TRUE) { //If the underline_right is TRUE
+						rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + 5, f->outline_color);
+					} else { //If the underline_right is FALSE
+						rectfill(bmp, first_x, final_y, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_left > 0) {
+					if (f->underline_left == FALSE) {
+						rectfill(bmp, first_x - 1, final_y, final_x, final_y + 5, f->outline_color);
+					}
+				}
+				if (f->outline_right > 0) {
+					if (f->underline_right == FALSE) {
+						rectfill(bmp, first_x, final_y, final_x + 1, final_y + 5, f->outline_color);
+					}
+				}
+			}
+			if (f->outline_hollow == FALSE) { //check if it is the masked region for outline
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					rectfill(bmp, first_x, final_y, final_x + f->ch_spacing, final_y + 5, color);
+				} else { //If the underline_right is FALSE
+					rectfill(bmp, first_x, final_y, final_x, final_y + 5, color);
+				}
+			} else {
+				//cancel transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+					}
+				}
+				if (f->underline_right == TRUE) { //If the underline_right is TRUE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x + f->ch_spacing - first_x + 1, final_y + 5 - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				} else { //If the underline_right is FALSE
+					masked_blit(masked_bmp, bmp, 0, 0, first_x, final_y, final_x - first_x + 1, final_y + 5 - final_y + 1);
+					destroy_bitmap(masked_bmp);
+				}
+				//restore transparency
+				if (f->transparency != 255) {
+					if (bitmap_color_depth(bmp) > 8) {
+						drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+					}
+				}
+			}
+		}
+	}
+
+	release_bitmap(bmp);
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW_pointer)
+			free(lpszW_pointer);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	}
+
+
+int alfont_text_height(ALFONT_FONT * f) {
+	return f->face_h;
+}
+
+
+int alfont_text_length(ALFONT_FONT * f, const char *str) {
+	char *lpszW;
+	char *lpszW_tmp;
+	int max_advancex = 0;
+	char *lpszW_pointer = NULL; //used for freeing string
+	char *str_pointer = NULL; //used for original string fixed by autofix
+	char *str_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int curr_uformat = 0;
+	int total_length = 0, character, last_glyph_index;
+	int glyph_index;
+	int glyph_index_tmp;
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (str == NULL) {
+		return 0;
+	}
+
+	nLen = strlen(str) + 1;
+	str_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(str_pointer, 0, nLen);
+	strcpy(str_pointer, str);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the str string
+	//If find the cutted character, store it from the converted str string and remove it from the original str string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(str) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the str string
+				if (f->precedingchar != 0) {
+					free(str_pointer);
+					fromlen = strlen(str) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					str_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(str_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(str_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(str_pointer, str);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = str;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				str_pointer_temp = str_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*str_pointer_temp != '\0') {
+						f->precedingchar = *str_pointer_temp;
+						str_pointer_temp++;
+					}
+					//remove the final character
+					str_pointer_temp--;
+					*str_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(str_pointer) * 5 + 1;
+#else
+			nLen = strlen(str_pointer) + 1;
+#endif
+
+			//add the previous character to the str string
+			if (f->precedingchar != 0) {
+				free(str_pointer);
+				nLen = strlen(str) + 1 + 1;
+				str_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(str_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(str_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(str_pointer, str);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, str_pointer, nLen);
+
+			str_pointer_temp = str_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*str_pointer_temp != '\0') {
+					f->precedingchar = *str_pointer_temp;
+					str_pointer_temp++;
+				}
+				//remove the final character
+				str_pointer_temp--;
+				*str_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)str_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(str_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = str_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)str_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)str_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		wcstombs(lpszW, (const wchar_t *)str_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)str_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(str_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = str_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)str_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(str_pointer) * 5 + 1;
+#else
+		nLen = strlen(str_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		mbstowcs((wchar_t *)lpszW, str_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(str_pointer) + 1;
+#endif
+		lpszW = (char *)str_pointer;
+	}
+
+	/* virtually draw char by char */
+	last_glyph_index = 0;
+
+	if (f->fixed_width == TRUE) {
+		lpszW_tmp = lpszW;
+		max_advancex = 0;
+
+		_alfont_uncache_glyphs(f);
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp), character = ugetxc((const char **)&lpszW_tmp)) {
+#else
+		for (character = ugetxc((const char **)&lpszW_tmp); character != 0; character = ugetxc((const char **)&lpszW_tmp)) {
+#endif
+			/* get the character out of the font */
+
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+			if (f->type != 2) {
+				lpszW_tmp--;
+			}
+#endif
+
+			/* get the character out of the font */
+			if (f->face->charmap)
+				glyph_index_tmp = FT_Get_Char_Index(f->face, character);
+			else
+				glyph_index_tmp = character;
+
+			/* cache the glyph */
+			_alfont_cache_glyph(f, glyph_index_tmp);
+			if (max_advancex < f->cached_glyphs[glyph_index_tmp].advancex)
+				max_advancex = f->cached_glyphs[glyph_index_tmp].advancex;
+		}
+		}
+
+#ifdef ALFONT_LINUX //Fix for Linux Unicode System(be converted)
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW), character = ugetxc((const char **)&lpszW)) {
+#else
+	for (character = ugetxc((const char **)&lpszW); character != 0; character = ugetxc((const char **)&lpszW)) {
+#endif
+		/* get the character out of the font */
+
+#ifdef ALFONT_LINUX //Recover for Linux Unicode System Fixed
+		if (f->type != 2) {
+			lpszW--;
+		}
+#endif
+
+		if (f->face->charmap)
+			glyph_index = FT_Get_Char_Index(f->face, character);
+		else
+			glyph_index = character;
+
+		/* apply kerning */
+		/*if (last_glyph_index) {
+			FT_Vector v;
+			FT_Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
+			total_length += v.x >> 6;
+		}*/
+		last_glyph_index = glyph_index;
+
+		/* cache */
+		_alfont_cache_glyph(f, glyph_index);
+		if (f->fixed_width == TRUE)
+			f->cached_glyphs[glyph_index].advancex = max_advancex;
+
+		/* advance */
+		if (f->cached_glyphs[glyph_index].advancex)
+			total_length += f->cached_glyphs[glyph_index].advancex + f->ch_spacing;
+	}
+
+	if ((f->style == 1) || (f->style == 3)) {
+		if (f->cached_glyphs[last_glyph_index].advancex)
+			total_length += (f->outline_right + 1) + (f->cached_glyphs[last_glyph_index].advancex / 2);
+	}
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW_pointer)
+			free(lpszW_pointer);
+	}
+
+	if (str_pointer) {
+		free(str_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return total_length;
+	}
+
+int alfont_char_length(ALFONT_FONT * f, int character) {
+	int curr_uformat = 0;
+	int total_length = 0, last_glyph_index;
+	int glyph_index;
+
+	if (character == 0) {
+		return 0;
+	}
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+		setlocale(LC_CTYPE, f->language);
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+#endif
+	}
+
+	/* virtually draw char by char */
+	last_glyph_index = 0;
+
+
+	/* get the character out of the font */
+
+	if (f->face->charmap)
+		glyph_index = FT_Get_Char_Index(f->face, character);
+	else
+		glyph_index = character;
+
+	/* apply kerning */
+	/*if (last_glyph_index) {
+	  FT_Vector v;
+	  FT_Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
+	  total_length += v.x >> 6;
+	}*/
+	last_glyph_index = glyph_index;
+
+	if (f->fixed_width == TRUE) {
+		_alfont_uncache_glyph_number(f, glyph_index);
+	}
+
+	/* cache */
+	_alfont_cache_glyph(f, glyph_index);
+
+	/* advance */
+	if (f->cached_glyphs[glyph_index].advancex)
+		total_length += f->cached_glyphs[glyph_index].advancex + f->ch_spacing;
+
+	if ((f->style == 1) || (f->style == 3)) {
+		if (f->cached_glyphs[last_glyph_index].advancex)
+			total_length += (f->outline_right + 1) + (f->cached_glyphs[last_glyph_index].advancex / 2);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return total_length;
+}
+
+int alfont_text_count(ALFONT_FONT * f, const char *str) {
+	char *lpszW;
+	char *lpszW_pointer = NULL; //used for freeing string
+	char *str_pointer = NULL; //used for original string fixed by autofix
+	char *str_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int curr_uformat = 0;
+	int string_count = 0;
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (str == NULL) {
+		return 0;
+	}
+
+	nLen = strlen(str) + 1;
+	str_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(str_pointer, 0, nLen);
+	strcpy(str_pointer, str);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the str string
+	//If find the cutted character, store it from the converted str string and remove it from the original str string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(str) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the str string
+				if (f->precedingchar != 0) {
+					free(str_pointer);
+					fromlen = strlen(str) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					str_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(str_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(str_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(str_pointer, str);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = str;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				str_pointer_temp = str_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*str_pointer_temp != '\0') {
+						f->precedingchar = *str_pointer_temp;
+						str_pointer_temp++;
+					}
+					//remove the final character
+					str_pointer_temp--;
+					*str_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(str_pointer) * 5 + 1;
+#else
+			nLen = strlen(str_pointer) + 1;
+#endif
+
+			//add the previous character to the str string
+			if (f->precedingchar != 0) {
+				free(str_pointer);
+				nLen = strlen(str) + 1 + 1;
+				str_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(str_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(str_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(str_pointer, str);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, str_pointer, nLen);
+
+			str_pointer_temp = str_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*str_pointer_temp != '\0') {
+					f->precedingchar = *str_pointer_temp;
+					str_pointer_temp++;
+				}
+				//remove the final character
+				str_pointer_temp--;
+				*str_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)str_pointer;
+			string_count = strlen(lpszW);
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(str_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = str_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)str_pointer;
+			}
+			string_count = strlen(lpszW);
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)str_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		string_count = wcstombs(lpszW, (const wchar_t *)str_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)str_pointer;
+			string_count = strlen(lpszW);
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(str_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			lpszW_pointer = lpszW;
+			sin = str_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)str_pointer;
+				string_count = strlen(lpszW);
+			} else {
+				set_uformat(U_UNICODE);
+				string_count = ustrlen(lpszW);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(str_pointer) * 5 + 1;
+#else
+		nLen = strlen(str_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		lpszW_pointer = lpszW;
+		string_count = mbstowcs((wchar_t *)lpszW, str_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(str_pointer) + 1;
+		string_count = ustrlen(str_pointer);
+#else
+		string_count = strlen(str_pointer);
+#endif
+		lpszW = (char *)str_pointer;
+
+	}
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW_pointer)
+			free(lpszW_pointer);
+	}
+
+	if (str_pointer) {
+		free(str_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return string_count;
+}
+
+int alfont_ugetc(ALFONT_FONT * f, const char *s) {
+	char *lpszW;
+//	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int character;
+	int curr_uformat = 0;
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (s == NULL) {
+		return 0;
+	}
+
+	nLen = strlen(s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the s string
+	//If find the cutted character, store it from the converted s string and remove it from the original s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	character = ugetc((const char *)lpszW);
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW)
+			free(lpszW);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return character;
+}
+
+int alfont_ugetx(ALFONT_FONT * f, char **s) {
+	char *lpszW;
+//	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int character;
+	int curr_uformat = 0;
+
+	char *lpszWS;
+	char *lpszWA;
+	int sLen; //length before advances the *s pointer to the next character
+	int aLen; //length after advances the *s pointer to the next character
+	int lIndex;
+
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (*s == NULL) {
+		return 0;
+	}
+
+	sLen = strlen(*s);
+
+	nLen = strlen(*s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, *s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the *s string
+	//If find the cutted character, store it from the converted *s string and remove it from the original *s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(*s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the *s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(*s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, *s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = *s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the *s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(*s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, *s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	lpszWS = lpszW;
+	character = ugetc((const char *)lpszW);
+
+	//advances the *s pointer to the next character
+
+	if (f->type == 1) {
+		ugetxc((const char **)s);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)s);
+#endif
+	} else if (f->type == 2) {
+		ugetxc((const char **)&lpszWS);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)&lpszWS);
+#endif
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			aLen = strlen(lpszWS);
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(lpszWS) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszWA = (char *)malloc(tolen * sizeof(char));
+			memset(lpszWA, 0, tolen);
+			sin = lpszWS;
+			sout = lpszWA;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				if (lpszWA)
+					free(lpszWA);
+				lpszWA = lpszWS
+			}
+			aLen = strlen(lpszWA);
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)lpszWS) + 1;
+		lpszWA = (char *)malloc(nLen * sizeof(char));
+		memset(lpszWA, 0, nLen);
+		wcstombs(lpszWA, (const wchar_t *)lpszWS, nLen);
+		aLen = strlen(lpszWA);
+#endif
+
+		for (lIndex = 0; lIndex < sLen - aLen; lIndex++) {
+			(*(*s)++);
+		}
+
+		if (lpszWA) {
+			free(lpszWA);
+		}
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+#endif
+		ugetxc((const char **)s);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)s);
+#endif
+	}
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW)
+			free(lpszW);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return character;
+}
+
+int alfont_ugetxc(ALFONT_FONT * f, const char **s) {
+	char *lpszW;
+//	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int character;
+	int curr_uformat = 0;
+
+	char *lpszWS;
+	char *lpszWA;
+	int sLen; //length before advances the *s pointer to the next character
+	int aLen; //length after advances the *s pointer to the next character
+	int lIndex;
+
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (*s == NULL) {
+		return 0;
+	}
+
+	sLen = strlen(*s);
+
+	nLen = strlen(*s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, *s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the *s string
+	//If find the cutted character, store it from the converted *s string and remove it from the original *s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(*s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the *s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(*s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, *s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = *s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the *s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(*s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, *s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	lpszWS = lpszW;
+	character = ugetc((const char *)lpszW);
+
+	//advances the *s pointer to the next character
+
+	if (f->type == 1) {
+		ugetxc((const char **)s);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)s);
+#endif
+	} else if (f->type == 2) {
+		ugetxc((const char **)&lpszWS);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)&lpszWS);
+#endif
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			aLen = strlen(lpszWS);
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(lpszWS) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszWA = (char *)malloc(tolen * sizeof(char));
+			memset(lpszWA, 0, tolen);
+			sin = lpszWS;
+			sout = lpszWA;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				if (lpszWA)
+					free(lpszWA);
+				lpszWA = lpszWS
+			}
+			aLen = strlen(lpszWA);
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)lpszWS) + 1;
+		lpszWA = (char *)malloc(nLen * sizeof(char));
+		memset(lpszWA, 0, nLen);
+		wcstombs(lpszWA, (const wchar_t *)lpszWS, nLen);
+		aLen = strlen(lpszWA);
+#endif
+
+		for (lIndex = 0; lIndex < sLen - aLen; lIndex++) {
+			(*(*s)++);
+		}
+
+		if (lpszWA) {
+			free(lpszWA);
+		}
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+#endif
+		ugetxc((const char **)s);
+#ifdef ALFONT_LINUX
+		ugetxc((const char **)s);
+#endif
+	}
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW)
+			free(lpszW);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return character;
+}
+
+// Following function alfont_get_string is removed from compilation because it 
+// is implemented with the use of non-standart malloc_usable_size function
+// (defined as _msize). This may cause linking errors on some Linux systems or
+// if using particular compilers.
+#if 0
+
+void alfont_get_string(ALFONT_FONT * f, const char *s, char **out) {
+	char *lpszW;
+	char *lpszW_pointer = NULL; //used for freeing string
+	char *s_pointer = NULL; //used for original string fixed by autofix
+	char *s_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int curr_uformat;
+
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
+
+	if (s == NULL) {
+		return;
+	}
+
+	nLen = strlen(s) + 1;
+	s_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(s_pointer, 0, nLen);
+	strcpy(s_pointer, s);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the s string
+	//If find the cutted character, store it from the converted s string and remove it from the original s string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(s) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the s string
+				if (f->precedingchar != 0) {
+					free(s_pointer);
+					fromlen = strlen(s) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					s_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(s_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(s_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(s_pointer, s);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = s;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				s_pointer_temp = s_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*s_pointer_temp != '\0') {
+						f->precedingchar = *s_pointer_temp;
+						s_pointer_temp++;
+					}
+					//remove the final character
+					s_pointer_temp--;
+					*s_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
+#else
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(s_pointer) * 5 + 1;
+#else
+			nLen = strlen(s_pointer) + 1;
+#endif
+
+			//add the previous character to the s string
+			if (f->precedingchar != 0) {
+				free(s_pointer);
+				nLen = strlen(s) + 1 + 1;
+				s_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(s_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(s_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(s_pointer, s);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+
+			s_pointer_temp = s_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*s_pointer_temp != '\0') {
+					f->precedingchar = *s_pointer_temp;
+					s_pointer_temp++;
+				}
+				//remove the final character
+				s_pointer_temp--;
+				*s_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	//Font Code Convert
+
+
+	if (f->type == 1) {
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open(f->language, "UTF-16LE")) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			}
+		}
+#else
+		setlocale(LC_CTYPE, f->language);
+		nLen = MB_CUR_MAX * wcslen((const wchar_t *)s_pointer) + 1;
+		lpszW = (char *)malloc(nLen * sizeof(char));
+		memset(lpszW, 0, nLen);
+		wcstombs(lpszW, (const wchar_t *)s_pointer, nLen);
+#endif
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+		if ((c_pt = iconv_open("UTF-16LE", f->language)) == (iconv_t)-1) {
+			lpszW = (char *)s_pointer;
+		} else {
+			iconv(c_pt, NULL, NULL, NULL, NULL);
+			fromlen = strlen(s_pointer) + 1;
+			tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+			lpszW = (char *)malloc(tolen * sizeof(char));
+			memset(lpszW, 0, tolen);
+			sin = s_pointer;
+			sout = lpszW;
+			ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+			iconv_close(c_pt);
+			if (ret == -1) {
+				lpszW = (char *)s_pointer;
+			} else {
+				set_uformat(U_UNICODE);
+			}
 		}
-		_fonts[_size] = font;
-		assert(_fonts[_size]);
+#else
+		setlocale(LC_CTYPE, f->language);
+		set_uformat(U_UNICODE);
+
+#ifdef ALFONT_LINUX
+		nLen = strlen(s_pointer) * 5 + 1;
+#else
+		nLen = strlen(s_pointer) + 1;
+#endif
+
+		lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+		memset(lpszW, 0, nLen);
+		mbstowcs((wchar_t *)lpszW, s_pointer, nLen);
+#endif
+	} else {
+#ifdef ALFONT_LINUX
+		set_uformat(U_UTF8);
+		nLen = ustrlen(s_pointer) + 1;
+#endif
+		lpszW = (char *)s_pointer;
+	}
+
+	memset(*out, 0, _msize(*out));
+	if (_msize(*out) > 0 && _msize(lpszW) >= _msize(*out)) {
+		memcpy(*out, lpszW, _msize(*out));
+	} else if (_msize(*out) > 0 && _msize(*out) > _msize(lpszW)) {
+		memcpy(*out, lpszW, _msize(lpszW));
+	}
+
+	if ((f->type == 1) || (f->type == 2)) {
+		if (lpszW)
+			free(lpszW);
+	}
+
+	if (s_pointer) {
+		free(s_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
+#endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+}
+
+#endif // DISABLED
+
+int alfont_need_uconvert(ALFONT_FONT * f, const char *str) {
+	char *lpszW;
+	char *str_pointer = NULL; //used for original string fixed by autofix
+	char *str_pointer_temp = NULL; //temporary used for autofix string
+	char *precedingchar_pointer = NULL; //used for precedingchar character
+	int need_unicode_convert = TRUE;
+	int nLen;
+	int ret; //decide that if the ASCII Code convert to Unicode Code is all OK when used for autofix string or used for general convert.
+	int curr_uformat = 0;
+#ifdef ALFONT_DOS
+	iconv_t c_pt;
+	size_t fromlen, tolen;
+	char *sin, *sout;
+#endif
 
-		_fontName = _fonts[_size]->getFontName();
+	if (str == NULL) {
+		return FALSE;
 	}
 
-	return _fonts[_size];
+	nLen = strlen(str) + 1;
+	str_pointer = (char *)malloc(nLen * sizeof(char));
+	memset(str_pointer, 0, nLen);
+	strcpy(str_pointer, str);
+
+	//Auto Fix for cutted string
+	//For ASCII convert to unicode
+	//Add the previous character to the str string
+	//If find the cutted character, store it from the converted str string and remove it from the original str string
+	if (f->autofix == TRUE) {
+		if (f->type == 2) {
+			curr_uformat = get_uformat();
+
+#ifdef ALFONT_DOS
+			if ((c_pt = iconv_open("UTF-16LE", f->language)) != (iconv_t)-1) {
+
+				fromlen = strlen(str) + 1;
+				tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+
+				//add the previous character to the str string
+				if (f->precedingchar != 0) {
+					free(str_pointer);
+					fromlen = strlen(str) + 1 + 1;
+					tolen = MB_CUR_MAX * fromlen * (sizeof(wchar_t) + 1);
+					str_pointer = (char *)malloc(tolen * sizeof(char));
+					memset(str_pointer, 0, tolen);
+					precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+					memset(precedingchar_pointer, 0, 2);
+					sprintf(precedingchar_pointer, "%c", f->precedingchar);
+					strcpy(str_pointer, precedingchar_pointer);
+					if (precedingchar_pointer) {
+						free(precedingchar_pointer);
+						precedingchar_pointer = NULL;
+					}
+					strcat(str_pointer, str);
+					f->precedingchar = 0;
+				}
+
+				iconv(c_pt, NULL, NULL, NULL, NULL);
+				lpszW = (char *)malloc(tolen * sizeof(char));
+				memset(lpszW, 0, tolen);
+				sin = str;
+				sout = lpszW;
+				ret = iconv(c_pt, &sin, &fromlen, &sout, &tolen);
+				iconv_close(c_pt);
+
+				str_pointer_temp = str_pointer;
+
+				if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+					//store the last character to precedingchar character
+					//get the final character
+					set_uformat(curr_uformat);
+					while (*str_pointer_temp != '\0') {
+						f->precedingchar = *str_pointer_temp;
+						str_pointer_temp++;
+					}
+					//remove the final character
+					str_pointer_temp--;
+					*str_pointer_temp = '\0';
+				}
+				if (lpszW) {
+					free(lpszW);
+					lpszW = NULL;
+				}
+			}
 #else
-	error("Game needs FreeType library, which was not included in this build");
+
+
+#ifdef ALFONT_LINUX
+			nLen = strlen(str_pointer) * 5 + 1;
+#else
+			nLen = strlen(str_pointer) + 1;
+#endif
+
+			//add the previous character to the str string
+			if (f->precedingchar != 0) {
+				free(str_pointer);
+				nLen = strlen(str) + 1 + 1;
+				str_pointer = (char *)malloc(nLen * sizeof(char));
+				memset(str_pointer, 0, nLen);
+				precedingchar_pointer = (char *)malloc(2 * sizeof(char));
+				memset(precedingchar_pointer, 0, 2);
+				sprintf(precedingchar_pointer, "%c", f->precedingchar);
+				strcpy(str_pointer, precedingchar_pointer);
+				if (precedingchar_pointer) {
+					free(precedingchar_pointer);
+					precedingchar_pointer = NULL;
+				}
+				strcat(str_pointer, str);
+				f->precedingchar = 0;
+			}
+
+			setlocale(LC_CTYPE, f->language);
+			set_uformat(U_UNICODE);
+
+			lpszW = (char *)malloc(nLen * sizeof(wchar_t));
+			memset(lpszW, 0, nLen);
+			ret = mbstowcs((wchar_t *)lpszW, str_pointer, nLen);
+
+			str_pointer_temp = str_pointer;
+
+			if (ret == -1) { //If the ret is -1, the final one will can be a shortcutted character.
+				//store the last character to precedingchar character
+				//get the final character
+				set_uformat(curr_uformat);
+				while (*str_pointer_temp != '\0') {
+					f->precedingchar = *str_pointer_temp;
+					str_pointer_temp++;
+				}
+				//remove the final character
+				str_pointer_temp--;
+				*str_pointer_temp = '\0';
+			}
+			if (lpszW) {
+				free(lpszW);
+				lpszW = NULL;
+			}
+#endif
+			//recover to original codepage
+			set_uformat(curr_uformat);
+		}
+	}
+
+
+	if (f->type == 1) {
+		need_unicode_convert = FALSE;
+	} else if (f->type == 2) {
+		curr_uformat = get_uformat();
+
+		if (!need_uconvert(str_pointer, U_ASCII, U_UTF8)) {
+			need_unicode_convert = FALSE;
+		}
+	} else {
+		need_unicode_convert = FALSE;
+	}
+
+	if (str_pointer) {
+		free(str_pointer);
+	}
+
+#ifndef ALFONT_DOS
+	setlocale(LC_CTYPE, "");
 #endif
+
+	if (f->type == 2) {
+		set_uformat(curr_uformat);
+	}
+
+	return need_unicode_convert;
+}
+
+
+void alfont_textout_centre_aa(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color) {
+	alfont_textout_centre_aa_ex(bmp, f, s, x, y, color, alfont_textmode);
+}
+
+
+void alfont_textout_centre_aa_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color, int backg) {
+	x -= alfont_text_length(f, s) / 2;
+	alfont_textout_aa_ex(bmp, f, s, x, y, color, backg);
 }
 
-/*------------------------------------------------------------------*/
 
-ALFONT_FONT *alfont_load_font_from_mem(const byte *data, int data_len) {
-	return new ALFONT_FONT(data, data_len);
+void alfont_textout_centre(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color) {
+	alfont_textout_centre_ex(bmp, f, s, x, y, color, alfont_textmode);
 }
 
-void alfont_destroy_font(ALFONT_FONT *font) {
-	delete font;
+
+void alfont_textout_centre_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color, int backg) {
+	x -= alfont_text_length(f, s) / 2;
+	alfont_textout_ex(bmp, f, s, x, y, color, backg);
 }
 
-size_t alfont_text_length(ALFONT_FONT *font, const char *text) {
-	return font->getFont()->getStringWidth(text);
+
+void alfont_textout_right_aa(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color) {
+	alfont_textout_right_aa_ex(bmp, f, s, x, y, color, alfont_textmode);
 }
 
-size_t alfont_text_height(ALFONT_FONT *font) {
-	return font->_size;
+
+void alfont_textout_right_aa_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color, int backg) {
+	x -= alfont_text_length(f, s);
+	alfont_textout_aa_ex(bmp, f, s, x, y, color, backg);
 }
 
-void alfont_textout(BITMAP *bmp, ALFONT_FONT *font, ALFONT_FONT *refFont, const char *text, int x, int y, uint32 color) {
-	// Note: the original does not use antialiasing when drawing on 8 bit bmp
-	// if (bitmap_color_depth(bmp) > 8) do not use AA in getFont()...
-	// The original alfont changes the y based on the font height and ascent.
-	y += (font->_size - font->getFont()->getFontAscent());
-	Graphics::ManagedSurface &surf = **bmp;
-	Graphics::Font *fnt = font->getFont();
-	uint32 col = (color == surf.getTransparentColor()) ? color - 1 : color;
 
-	if (!refFont) {
-		// Standard string draw
-		fnt->drawString(&surf, text, x, y, bmp->w - x, col);
+void alfont_textout_right(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color) {
+	alfont_textout_right_ex(bmp, f, s, x, y, color, alfont_textmode);
+}
+
 
-	} else {
-		// Drawing an outline prior to standard font drawing on top.
-		// We use the font's character widths to ensure the two match up
-		refFont->_size = font->_size;
-		Graphics::Font *srcFnt = refFont->getFont();
+void alfont_textout_right_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int y, int color, int backg) {
+	x -= alfont_text_length(f, s);
+	alfont_textout_ex(bmp, f, s, x, y, color, backg);
+}
 
-		for (int w = bmp->w - x; *text && w > 0; ++text) {
-			fnt->drawChar(&surf, *text, x, y, col);
 
-			int charWidth = srcFnt->getCharWidth(*text);
-			x += charWidth;
-			w -= charWidth;
-		}
+void alfont_textprintf(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+void alfont_textprintf_aa(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_aa(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_aa_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_aa_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+void alfont_textprintf_centre(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_centre(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_centre_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_centre_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+void alfont_textprintf_centre_aa(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_centre_aa(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_centre_aa_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_centre_aa_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+void alfont_textprintf_right(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_right(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_right_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_right_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+void alfont_textprintf_right_aa(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_right_aa(bmp, f, buf, x, y, color);
+}
+
+
+void alfont_textprintf_right_aa_ex(BITMAP * bmp, ALFONT_FONT * f, int x, int y, int color, int backg, const char *format, ...) {
+	char buf[512];
+
+	va_list ap;
+	set_uformat(U_ASCII);
+	va_start(ap, format);
+	uvszprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	alfont_textout_right_aa_ex(bmp, f, buf, x, y, color, backg);
+}
+
+
+int alfont_is_fixed_font(ALFONT_FONT * f) {
+	if (f->num_fixed_sizes < 0)
+		return FALSE;
+	else
+		return TRUE;
+}
+
+
+int alfont_is_scalable_font(ALFONT_FONT * f) {
+	if (f->num_fixed_sizes < 0)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+const int *alfont_get_available_fixed_sizes(ALFONT_FONT * f) {
+	/* we reget them just to make sure the contents where not changed */
+	_alfont_reget_fixed_sizes(f);
+	return f->fixed_sizes;
+}
+
+
+int alfont_get_nof_available_fixed_sizes(ALFONT_FONT * f) {
+	return f->num_fixed_sizes;
+}
+
+
+int alfont_get_char_extra_spacing(ALFONT_FONT * f) {
+	return f->ch_spacing;
+}
+
+
+void alfont_set_char_extra_spacing(ALFONT_FONT * f, int spacing) {
+	if (spacing < 0)
+		f->ch_spacing = 0;
+	else if (spacing > 4096)
+		f->ch_spacing = 4096;
+	else
+		f->ch_spacing = spacing;
+}
+
+
+void alfont_set_language(ALFONT_FONT * f, const char *language) {
+	if (language == NULL) {
+		f->language = NULL;
+	} else {
+		f->language = (char *)malloc((strlen(language) + 1) * sizeof(char));
+		strcpy(f->language, language);
 	}
 }
 
-void alfont_set_font_size(ALFONT_FONT *font, int size) {
-	font->_size = size;
+
+char *alfont_get_language(ALFONT_FONT * f) {
+	return f->language;
+}
+
+
+void alfont_set_convert(ALFONT_FONT * f, int type) {
+	if (type < 0)
+		f->type = 0;
+	else if (type > 2)
+		f->type = 2;
+	else
+		f->type = type;
+}
+
+
+int alfont_get_convert(ALFONT_FONT * f) {
+	return f->type;
+}
+
+
+void alfont_set_font_outline_top(ALFONT_FONT * f, int w) {
+	if (w < 0)
+		f->outline_top = 0;
+	else
+		f->outline_top = w;
+}
+
+
+int alfont_get_font_outline_top(ALFONT_FONT * f) {
+	return f->outline_top;
+}
+
+
+void alfont_set_font_outline_bottom(ALFONT_FONT * f, int w) {
+	if (w < 0)
+		f->outline_bottom = 0;
+	else
+		f->outline_bottom = w;
+}
+
+
+int alfont_get_font_outline_bottom(ALFONT_FONT * f) {
+	return f->outline_bottom;
+}
+
+
+void alfont_set_font_outline_right(ALFONT_FONT * f, int w) {
+	if (w < 0)
+		f->outline_right = 0;
+	else
+		f->outline_right = w;
+}
+
+
+int alfont_get_font_outline_right(ALFONT_FONT * f) {
+	return f->outline_right;
+}
+
+
+void alfont_set_font_outline_left(ALFONT_FONT * f, int w) {
+	if (w < 0)
+		f->outline_left = 0;
+	else
+		f->outline_left = w;
+}
+
+
+int alfont_get_font_outline_left(ALFONT_FONT * f) {
+	return f->outline_left;
+}
+
+
+void alfont_set_font_outline_color(ALFONT_FONT * f, int c) {
+	if (c < 0)
+		f->outline_color = 0;
+	else
+		f->outline_color = c;
+}
+
+
+int alfont_get_font_outline_color(ALFONT_FONT * f) {
+	return f->outline_color;
+}
+
+
+void alfont_set_font_outline_hollow(ALFONT_FONT * f, int hollow) {
+	if (hollow == FALSE)
+		f->outline_hollow = FALSE;
+	else
+		f->outline_hollow = TRUE;
+}
+
+
+int alfont_get_font_outline_hollow(ALFONT_FONT * f) {
+	return f->outline_hollow;
+}
+
+
+void alfont_set_font_style(ALFONT_FONT * f, int style) {
+	if (style < 0)
+		f->style = 0;
+	else if (style > 3)
+		f->style = 3;
+	else
+		f->style = style;
+}
+
+
+int alfont_get_font_style(ALFONT_FONT * f) {
+	return f->style;
+}
+
+
+void alfont_set_font_underline(ALFONT_FONT * f, int underline) {
+	if (underline == FALSE)
+		f->underline = FALSE;
+	else
+		f->underline = TRUE;
+}
+
+
+int alfont_get_font_underline(ALFONT_FONT * f) {
+	return f->underline;
+}
+
+
+void alfont_set_font_underline_right(ALFONT_FONT * f, int underline_right) {
+	if (underline_right == FALSE)
+		f->underline_right = FALSE;
+	else
+		f->underline_right = TRUE;
+}
+
+
+int alfont_get_font_underline_right(ALFONT_FONT * f) {
+	return f->underline_right;
+}
+
+
+void alfont_set_font_underline_left(ALFONT_FONT * f, int underline_left) {
+	if (underline_left == FALSE)
+		f->underline_left = FALSE;
+	else
+		f->underline_left = TRUE;
+}
+
+
+int alfont_get_font_underline_left(ALFONT_FONT * f) {
+	return f->underline_left;
+}
+
+
+void alfont_set_font_background(ALFONT_FONT * f, int background) {
+	if (background == FALSE)
+		f->background = FALSE;
+	else
+		f->background = TRUE;
+}
+
+
+int alfont_get_font_background(ALFONT_FONT * f) {
+	return f->background;
+}
+
+
+void alfont_set_font_transparency(ALFONT_FONT * f, int transparency) {
+	f->transparency = transparency;
+}
+
+
+int alfont_get_font_transparency(ALFONT_FONT * f) {
+	return f->transparency;
+}
+
+
+void alfont_set_autofix(ALFONT_FONT * f, int autofix) {
+	if (autofix == FALSE)
+		f->autofix = FALSE;
+	else
+		f->autofix = TRUE;
+}
+
+
+int alfont_get_autofix(ALFONT_FONT * f) {
+	return f->autofix;
 }
 
-int alfont_get_font_height(ALFONT_FONT *font) {
-	return font->_size;
+
+void alfont_set_precedingchar(ALFONT_FONT * f, int precedingchar) {
+	f->precedingchar = precedingchar;
 }
 
-int alfont_get_font_real_height(ALFONT_FONT *font) {
-	return font->_size;
+
+int alfont_get_precedingchar(ALFONT_FONT * f) {
+	return f->precedingchar;
 }
 
-const char *alfont_get_name(ALFONT_FONT *font) {
-	(void)font->getFont();	// Ensure a font is loaded
-	return font->_fontName.c_str();
+ALFONT_DLL_DECLSPEC void alfont_set_font_fixed_width(ALFONT_FONT * f, int fixed_width) {
+	if (fixed_width == FALSE)
+		f->fixed_width = FALSE;
+	else
+		f->fixed_width = TRUE;
+	_alfont_uncache_glyphs(f);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/lib/alfont/alfont.h b/engines/ags/lib/alfont/alfont.h
index 3803e1eda6c..b26c2413f7e 100644
--- a/engines/ags/lib/alfont/alfont.h
+++ b/engines/ags/lib/alfont/alfont.h
@@ -22,44 +22,87 @@
 #ifndef AGS_LIB_ALFONT_H
 #define AGS_LIB_ALFONT_H
 
-#include "common/hashmap.h"
-#include "common/memstream.h"
-#include "graphics/font.h"
-#include "ags/lib/allegro/gfx.h"
+#include "ags/lib/allegro/surface.h"
 
 namespace AGS3 {
 
-struct ALFONT_FONT {
-	Common::MemoryReadStream _ttfData;
-	int _size;
-	Common::HashMap<int, Graphics::Font *> _fonts;
-	Common::String _fontName;
-
-	ALFONT_FONT() : _size(-1), _ttfData(nullptr, 0) {}
-	ALFONT_FONT(const byte *data, int size) : _size(-1), _ttfData(data, size, DisposeAfterUse::YES) {}
-
-	~ALFONT_FONT() {
-		for (Common::HashMap<int, Graphics::Font *>::iterator it = _fonts.begin();
-				it != _fonts.end(); ++it)
-			delete(*it)._value;
-	}
-
-	Graphics::Font *getFont();
-};
-
-inline void alfont_init() {}
-inline void alfont_exit() {}
-inline void alfont_text_mode(int val) {}
-extern ALFONT_FONT *alfont_load_font_from_mem(const byte *data, int data_len);
-extern void alfont_destroy_font(ALFONT_FONT *font);
-
-extern size_t alfont_text_length(ALFONT_FONT *font, const char *text);
-extern size_t alfont_text_height(ALFONT_FONT *font);
-extern void alfont_textout(BITMAP *bmp, ALFONT_FONT *font, ALFONT_FONT *refFont, const char *text, int x, int y, uint32 color);
-extern const char *alfont_get_name(ALFONT_FONT *font);
-extern void alfont_set_font_size(ALFONT_FONT *font, int size);
-extern int alfont_get_font_height(ALFONT_FONT *font);
-extern int alfont_get_font_real_height(ALFONT_FONT *font);
+/* common define */
+
+#define ALFONT_MAJOR_VERSION        1
+#define ALFONT_MINOR_VERSION        9
+#define ALFONT_SUB_VERSION          1
+#define ALFONT_VERSION_STR          "1.9.1"
+#define ALFONT_DATE_STR             "24/11/2002"
+#define ALFONT_DATE                 20021124    /* yyyymmdd */
+
+/* error codes */
+
+#define ALFONT_OK                   0
+#define ALFONT_ERROR                -1
+
+/* structs */
+typedef struct ALFONT_FONT ALFONT_FONT;
+
+/* API */
+#define ALFONT_DLL_DECLSPEC
+
+ALFONT_DLL_DECLSPEC const char *alfont_get_name(ALFONT_FONT *f);
+
+ALFONT_DLL_DECLSPEC int alfont_init(void);
+ALFONT_DLL_DECLSPEC void alfont_exit(void);
+
+ALFONT_DLL_DECLSPEC ALFONT_FONT *alfont_load_font(const char *filepathname);
+ALFONT_DLL_DECLSPEC ALFONT_FONT *alfont_load_font_from_mem(const char *data, int data_len);
+ALFONT_DLL_DECLSPEC void alfont_destroy_font(ALFONT_FONT *f);
+
+ALFONT_DLL_DECLSPEC int alfont_set_font_size(ALFONT_FONT *f, int h);
+ALFONT_DLL_DECLSPEC int alfont_get_font_height(ALFONT_FONT *f);
+/* Returns the real font graphical height */
+ALFONT_DLL_DECLSPEC int alfont_get_font_real_height(ALFONT_FONT *f);
+
+ALFONT_DLL_DECLSPEC int alfont_text_mode(int mode);
+
+ALFONT_DLL_DECLSPEC void alfont_textout_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+ALFONT_DLL_DECLSPEC void alfont_textout_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+
+ALFONT_DLL_DECLSPEC void alfont_textout_centre_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout_centre(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+ALFONT_DLL_DECLSPEC void alfont_textout_centre_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+
+ALFONT_DLL_DECLSPEC void alfont_textout_right_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout_right(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+ALFONT_DLL_DECLSPEC void alfont_textout_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+ALFONT_DLL_DECLSPEC void alfont_textout_right_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg);
+
+ALFONT_DLL_DECLSPEC void alfont_textprintf(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+
+ALFONT_DLL_DECLSPEC void alfont_textprintf_centre(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+
+ALFONT_DLL_DECLSPEC void alfont_textprintf_right(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_right_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_right_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+ALFONT_DLL_DECLSPEC void alfont_textprintf_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...);
+
+ALFONT_DLL_DECLSPEC int alfont_text_height(ALFONT_FONT *f);
+ALFONT_DLL_DECLSPEC int alfont_text_length(ALFONT_FONT *f, const char *str);
+
+ALFONT_DLL_DECLSPEC int alfont_is_fixed_font(ALFONT_FONT *f);
+ALFONT_DLL_DECLSPEC int alfont_is_scalable_font(ALFONT_FONT *f);
+
+ALFONT_DLL_DECLSPEC const int *alfont_get_available_fixed_sizes(ALFONT_FONT *f);
+ALFONT_DLL_DECLSPEC int alfont_get_nof_available_fixed_sizes(ALFONT_FONT *f);
+
+ALFONT_DLL_DECLSPEC int alfont_get_char_extra_spacing(ALFONT_FONT *f);
+ALFONT_DLL_DECLSPEC void alfont_set_char_extra_spacing(ALFONT_FONT *f, int spacing);
 
 } // namespace AGS3
 
diff --git a/engines/ags/lib/allegro/color.h b/engines/ags/lib/allegro/color.h
index d9737e95d15..3a6dba68bc4 100644
--- a/engines/ags/lib/allegro/color.h
+++ b/engines/ags/lib/allegro/color.h
@@ -83,6 +83,8 @@ enum BlenderMode {
 	kTintLightBlenderMode
 };
 
+extern int makecol(byte r, byte g, byte b);
+
 AL_ARRAY(const int, _rgb_scale_5);
 AL_ARRAY(const int, _rgb_scale_6);
 
diff --git a/engines/ags/lib/allegro/draw.cpp b/engines/ags/lib/allegro/draw.cpp
index 1112306ebd3..f210d9fee1b 100644
--- a/engines/ags/lib/allegro/draw.cpp
+++ b/engines/ags/lib/allegro/draw.cpp
@@ -23,6 +23,19 @@
 
 namespace AGS3 {
 
+void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor) {
+	// TODO: Drawing mode
+}
+
+void xor_mode(int on) {
+	// TODO: xor_mode
+	error("TODO: xor_mode");
+}
+
+void solid_mode(void) {
+	// TODO: solid_mode
+}
+
 void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, DrawMethod proc) {
 	int dx = x2 - x1;
 	int dy = y2 - y1;
diff --git a/engines/ags/lib/allegro/draw.h b/engines/ags/lib/allegro/draw.h
index bc25d8c4666..ef1aab3ac1b 100644
--- a/engines/ags/lib/allegro/draw.h
+++ b/engines/ags/lib/allegro/draw.h
@@ -21,12 +21,24 @@
 
 #include "ags/lib/allegro/base.h"
 #include "ags/lib/allegro/gfx.h"
+#include "ags/lib/allegro/surface.h"
 
 #ifndef AGS_LIB_ALLEGRO_DRAW_H
 #define AGS_LIB_ALLEGRO_DRAW_H
 
 namespace AGS3 {
 
+#define DRAW_MODE_SOLID             0        /* flags for drawing_mode() */
+#define DRAW_MODE_XOR               1
+#define DRAW_MODE_COPY_PATTERN      2
+#define DRAW_MODE_SOLID_PATTERN     3
+#define DRAW_MODE_MASKED_PATTERN    4
+#define DRAW_MODE_TRANS             5
+
+AL_FUNC(void, drawing_mode, (int mode, BITMAP *pattern, int x_anchor, int y_anchor));
+AL_FUNC(void, xor_mode, (int on));
+AL_FUNC(void, solid_mode, (void));
+
 typedef void (*DrawMethod)(BITMAP *, int, int, int);
 
 extern void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, DrawMethod proc);
diff --git a/engines/ags/lib/allegro/system.h b/engines/ags/lib/allegro/system.h
index de985ad56fb..b69079abe92 100644
--- a/engines/ags/lib/allegro/system.h
+++ b/engines/ags/lib/allegro/system.h
@@ -116,7 +116,6 @@ struct GFX_DRIVER {
 	AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y));
 	AL_METHOD(void, hide_mouse, (void));
 	AL_METHOD(void, move_mouse, (int x, int y));
-	AL_METHOD(void, drawing_mode, (void));
 	AL_METHOD(void, save_video_state, (void));
 	AL_METHOD(void, restore_video_state, (void));
 	AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a));
diff --git a/engines/ags/lib/allegro/unicode.cpp b/engines/ags/lib/allegro/unicode.cpp
index fbdb19ceecf..683a877485e 100644
--- a/engines/ags/lib/allegro/unicode.cpp
+++ b/engines/ags/lib/allegro/unicode.cpp
@@ -1283,4 +1283,18 @@ int ustrsizez(const char *s) {
 	return (intptr_t)s - (intptr_t)orig;
 }
 
+void setlocale(int type, const char *language) {
+	// TODO: If needed for alfont
+}
+
+int need_uconvert(const char *s, int type, int newtype) {
+	// TODO: need_uconvert
+	return 0;
+}
+
+int uvszprintf(char *buf, int size, const char *format, va_list args) {
+	error("TODO: uvszprintf");
+	return 0;
+}
+
 } // namespace AGS3
diff --git a/engines/ags/lib/allegro/unicode.h b/engines/ags/lib/allegro/unicode.h
index df38d5277a0..81c30746ef2 100644
--- a/engines/ags/lib/allegro/unicode.h
+++ b/engines/ags/lib/allegro/unicode.h
@@ -72,6 +72,9 @@ extern int (*uisok)(int c);
  */
 extern void set_uformat(int type);
 
+enum { LC_CTYPE };
+extern void setlocale(int type, const char *language);
+
 /* get_uformat:
  *  Returns the current text encoding format.
  */
@@ -134,6 +137,9 @@ int usetat(char *s, int index, int c);
  */
 extern int ustrsizez(const char *s);
 
+extern int need_uconvert(const char *s, int type, int newtype);
+extern int uvszprintf(char *buf, int size, const char *format, va_list args);
+
 } // namespace AGS3
 
 #endif
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index a2f208b4ab5..1a702b14d02 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -35,6 +35,7 @@ using namespace AGS::Shared;
 // project-specific implementation
 extern bool ShouldAntiAliasText();
 
+
 // ***** TTF RENDERER *****
 void TTFFontRenderer::AdjustYCoordinateForFont(int *ycoord, int fontNumber) {
 	// TTF fonts already have space at the top, so try to remove the gap
@@ -61,18 +62,11 @@ void TTFFontRenderer::RenderText(const char *text, int fontNumber, BITMAP *desti
 	if (y > destination->cb)  // optimisation
 		return;
 
-	int srcFontNum = get_font_outline_font(fontNumber);
-	ALFONT_FONT *srcFont = nullptr;
-	if (srcFontNum != FONT_OUTLINE_NONE) {
-		// Get the font without outline (if it's loaded) for use in
-		// character widths, so it will match when non-outlined font
-		// is drawn on top of it.
-		srcFont = _fontData[srcFontNum].AlFont;
-	}
-
 	// Y - 1 because it seems to get drawn down a bit
-	alfont_textout(destination, _fontData[fontNumber].AlFont,
-		srcFont, text, x, y - 1, colour);
+	if ((ShouldAntiAliasText()) && (bitmap_color_depth(destination) > 8))
+		alfont_textout_aa(destination, _fontData[fontNumber].AlFont, text, x, y - 1, colour);
+	else
+		alfont_textout(destination, _fontData[fontNumber].AlFont, text, x, y - 1, colour);
 }
 
 bool TTFFontRenderer::LoadFromDisk(int fontNumber, int fontSize) {
@@ -84,41 +78,25 @@ bool TTFFontRenderer::IsBitmapFont() {
 }
 
 bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
-		const FontRenderParams *params, FontMetrics *metrics) {
+	const FontRenderParams *params, FontMetrics *metrics) {
 	String file_name = String::FromFormat("agsfnt%d.ttf", fontNumber);
 	Stream *reader = _GP(AssetMgr)->OpenAsset(file_name);
-	byte *membuffer;
+	char *membuffer;
 
 	if (reader == nullptr)
 		return false;
 
-	size_t lenof = reader->GetLength();
-	membuffer = (byte *)malloc(lenof);
+	const size_t lenof = reader->GetLength();
+	membuffer = (char *)malloc(lenof);
 	reader->ReadArray(membuffer, lenof, 1);
 	delete reader;
 
 	ALFONT_FONT *alfptr = alfont_load_font_from_mem(membuffer, lenof);
+	free(membuffer);
 
-	if (alfptr == nullptr) {
-		free(membuffer);
+	if (alfptr == nullptr)
 		return false;
-	}
-
-	// TODO: move this somewhere, should not be right here
-#if defined(AGS_OUTLINE_FONT_FIX) && AGS_OUTLINE_FONT_FIX
-	// FIXME: (!!!) this fix should be done differently:
-	// 1. Find out which OUTLINE font was causing troubles;
-	// 2. Replace outline method ONLY if that troublesome font is used as outline.
-	// 3. Move this fix somewhere else!! (right after game load routine?)
-	//
-	// Check for the LucasFan font since it comes with an outline font that
-	// is drawn incorrectly with Freetype versions > 2.1.3.
-	// A simple workaround is to disable outline fonts for it and use
-	// automatic outline drawing.
-	if (get_font_outline(fontNumber) >= 0 &&
-	        strcmp(alfont_get_name(alfptr), "LucasFan-Font") == 0)
-		set_font_outline(fontNumber, FONT_OUTLINE_AUTO);
-#endif
+
 	if (fontSize == 0)
 		fontSize = 8; // compatibility fix
 	if (params && params->SizeMultiplier > 1)
@@ -132,8 +110,7 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	if (metrics) {
 		metrics->Height = alfont_get_font_height(alfptr);
 		metrics->RealHeight = alfont_get_font_real_height(alfptr);
-	}
-
+}
 	return true;
 }
 


Commit: 8e1a3d08dba987128c2bdecc141f35184c870d72
    https://github.com/scummvm/scummvm/commit/8e1a3d08dba987128c2bdecc141f35184c870d72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:13-07:00

Commit Message:
AGS: Add USE_FREETYPE2 guard to alfont

Changed paths:
    engines/ags/lib/alfont/alfont.cpp


diff --git a/engines/ags/lib/alfont/alfont.cpp b/engines/ags/lib/alfont/alfont.cpp
index b9a281cc4e5..da33941b092 100644
--- a/engines/ags/lib/alfont/alfont.cpp
+++ b/engines/ags/lib/alfont/alfont.cpp
@@ -19,6 +19,8 @@
  *
  */
 
+#ifdef USE_FREETYPE2
+
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
 #include "common/scummsys.h"
 #include "ags/lib/alfont/alfont.h"
@@ -4983,3 +4985,68 @@ ALFONT_DLL_DECLSPEC void alfont_set_font_fixed_width(ALFONT_FONT * f, int fixed_
 }
 
 } // namespace AGS3
+
+#else
+
+#include "common/textconsole.h"
+#include "ags/lib/allegro/gfx.h"
+
+namespace AGS3 {
+
+struct ALFONT_FONT {
+	int dummy;
+};
+
+const char *alfont_get_name(ALFONT_FONT *f) { return nullptr; }
+int alfont_init(void) {	return 0; }
+void alfont_exit(void) {}
+
+ALFONT_FONT *alfont_load_font(const char *filepathname) {
+	error("Game needs FreeType library, which was not included in this build");
+}
+
+ALFONT_FONT *alfont_load_font_from_mem(const char *data, int data_len) {
+	return alfont_load_font(nullptr);
+}
+
+void alfont_destroy_font(ALFONT_FONT *f) {}
+int alfont_set_font_size(ALFONT_FONT *f, int h) { return 0; }
+int alfont_get_font_height(ALFONT_FONT *f) { return 0; }
+int alfont_get_font_real_height(ALFONT_FONT *f) { return 0; }
+int alfont_text_mode(int mode) { return 0; }
+void alfont_textout_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {}
+void alfont_textout(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {}
+void alfont_textout_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textout_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textout_centre_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {}
+void alfont_textout_centre(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {}
+void alfont_textout_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textout_centre_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textout_right_aa(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color);
+void alfont_textout_right(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color) {}
+void alfont_textout_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textout_right_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int y, int color, int bg) {}
+void alfont_textprintf(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+void alfont_textprintf_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+void alfont_textprintf_centre(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_centre_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_centre_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+void alfont_textprintf_centre_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+void alfont_textprintf_right(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_right_aa(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, const char *format, ...) {}
+void alfont_textprintf_right_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+void alfont_textprintf_right_aa_ex(BITMAP *bmp, ALFONT_FONT *f, int x, int y, int color, int bg, const char *format, ...) {}
+int alfont_text_height(ALFONT_FONT *f) { return 0; }
+int alfont_text_length(ALFONT_FONT *f, const char *str) { return 0; }
+int alfont_is_fixed_font(ALFONT_FONT *f) { return 0; }
+int alfont_is_scalable_font(ALFONT_FONT *f) { return 0; }
+const int *alfont_get_available_fixed_sizes(ALFONT_FONT *f) { return nullptr; }
+int alfont_get_nof_available_fixed_sizes(ALFONT_FONT *f) { return 0; }
+int alfont_get_char_extra_spacing(ALFONT_FONT *f) { return 0; }
+void alfont_set_char_extra_spacing(ALFONT_FONT *f, int spacing) {}
+
+} // namespace AGS3
+
+#endif


Commit: 91bce9b2e98aa3e90fd326fc49cd8b987ccd1d3c
    https://github.com/scummvm/scummvm/commit/91bce9b2e98aa3e90fd326fc49cd8b987ccd1d3c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:13-07:00

Commit Message:
AGS: Implement xor_mode/solid_mode

Changed paths:
    engines/ags/lib/allegro/draw.cpp


diff --git a/engines/ags/lib/allegro/draw.cpp b/engines/ags/lib/allegro/draw.cpp
index f210d9fee1b..2a894ae8562 100644
--- a/engines/ags/lib/allegro/draw.cpp
+++ b/engines/ags/lib/allegro/draw.cpp
@@ -28,12 +28,11 @@ void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor) {
 }
 
 void xor_mode(int on) {
-	// TODO: xor_mode
-	error("TODO: xor_mode");
+	drawing_mode(on ? DRAW_MODE_XOR : DRAW_MODE_SOLID, NULL, 0, 0);
 }
 
 void solid_mode(void) {
-	// TODO: solid_mode
+	drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
 }
 
 void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, DrawMethod proc) {


Commit: f34cf7ce678951339e70f903365cf263561e533f
    https://github.com/scummvm/scummvm/commit/f34cf7ce678951339e70f903365cf263561e533f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:13-07:00

Commit Message:
AGS: Apply TTF ascender hack only by the engine's request

>From upstream 14679a430bf29acb6e511bb3799a5f99d9929463

Changed paths:
    engines/ags/lib/alfont/alfont.cpp
    engines/ags/lib/alfont/alfont.h
    engines/ags/shared/font/ttf_font_renderer.cpp


diff --git a/engines/ags/lib/alfont/alfont.cpp b/engines/ags/lib/alfont/alfont.cpp
index da33941b092..1da914588e0 100644
--- a/engines/ags/lib/alfont/alfont.cpp
+++ b/engines/ags/lib/alfont/alfont.cpp
@@ -406,10 +406,12 @@ static void _alfont_new_cache_glyph(ALFONT_FONT *f) {
 /* API */
 
 int alfont_set_font_size(ALFONT_FONT *f, int h) {
+	return alfont_set_font_size_ex(f, h, 0);
+}
+
+int alfont_set_font_size_ex(ALFONT_FONT *f, int h, int flags) {
 	int error, test_h, direction;
-	int real_height = 0;
-	// AGS COMPAT HACK: always set ascender to the formal font height
-	int do_ascender_hack = TRUE; // TODO: make a func arg?
+	int real_height;
 	/* check the font doesn't already use that w and h */
 	if (h == f->face_h)
 		return ALFONT_OK;
@@ -474,7 +476,7 @@ int alfont_set_font_size(ALFONT_FONT *f, int h) {
 		f->face_ascender = f->face->size->metrics.ascender >> 6;
 
 		// AGS COMPAT HACK: set ascender to the formal font height
-		if (do_ascender_hack) {
+		if ((flags & ALFONT_FLG_ASCENDER_EQ_HEIGHT) != 0) {
 			f->face_ascender = h;
 			f->real_face_h = h + abs(f->face->size->metrics.descender >> 6);
 		}
diff --git a/engines/ags/lib/alfont/alfont.h b/engines/ags/lib/alfont/alfont.h
index b26c2413f7e..f22a2447fab 100644
--- a/engines/ags/lib/alfont/alfont.h
+++ b/engines/ags/lib/alfont/alfont.h
@@ -40,6 +40,11 @@ namespace AGS3 {
 #define ALFONT_OK                   0
 #define ALFONT_ERROR                -1
 
+/* font adjustment flags (AGS compatibility hacks) */
+
+// Make ascender equal to formal font height
+#define ALFONT_FLG_ASCENDER_EQ_HEIGHT 0x01
+
 /* structs */
 typedef struct ALFONT_FONT ALFONT_FONT;
 
@@ -56,6 +61,7 @@ ALFONT_DLL_DECLSPEC ALFONT_FONT *alfont_load_font_from_mem(const char *data, int
 ALFONT_DLL_DECLSPEC void alfont_destroy_font(ALFONT_FONT *f);
 
 ALFONT_DLL_DECLSPEC int alfont_set_font_size(ALFONT_FONT *f, int h);
+ALFONT_DLL_DECLSPEC int alfont_set_font_size_ex(ALFONT_FONT *f, int h, int flags);
 ALFONT_DLL_DECLSPEC int alfont_get_font_height(ALFONT_FONT *f);
 /* Returns the real font graphical height */
 ALFONT_DLL_DECLSPEC int alfont_get_font_real_height(ALFONT_FONT *f);
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index 1a702b14d02..9d8b0369cac 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -19,11 +19,12 @@
  *
  */
 
+#include "ags/shared/font/ttf_font_renderer.h"
 #include "ags/lib/alfont/alfont.h"
 #include "ags/shared/core/platform.h"
+#include "ags/shared/ac/game_version.h"
 #include "ags/globals.h"
 #include "ags/shared/core/asset_manager.h"
-#include "ags/shared/font/ttf_font_renderer.h"
 #include "ags/shared/util/stream.h"
 #include "ags/shared/ac/game_struct_defines.h"
 #include "ags/shared/font/fonts.h"
@@ -97,12 +98,17 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	if (alfptr == nullptr)
 		return false;
 
-	if (fontSize == 0)
+	if (fontSize <= 0)
 		fontSize = 8; // compatibility fix
 	if (params && params->SizeMultiplier > 1)
 		fontSize *= params->SizeMultiplier;
-	if (fontSize > 0)
-		alfont_set_font_size(alfptr, fontSize);
+	// Compatibility: font ascender is always adjusted to the formal font's height;
+	// EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing
+	// (the reason is uncertain, but this is to emulate old engine's behavior).
+	int alfont_flags = 0;
+	if (!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
+		alfont_flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT;
+	alfont_set_font_size_ex(alfptr, fontSize, alfont_flags);
 
 	_fontData[fontNumber].AlFont = alfptr;
 	_fontData[fontNumber].Params = params ? *params : FontRenderParams();


Commit: f4935dbf393b4936bef012f1c1f0d6a0153d05b1
    https://github.com/scummvm/scummvm/commit/f4935dbf393b4936bef012f1c1f0d6a0153d05b1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:13-07:00

Commit Message:
AGS: Force readjust TTF fonts if the OPT_ANTIALIASFONTS changes

>From upstream 115119eeb009fc7f2c5820b47bb866acad6498ec

Changed paths:
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/lib/alfont/alfont.cpp
    engines/ags/lib/alfont/alfont.h
    engines/ags/shared/font/ags_font_renderer.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/fonts.h
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/font/ttf_font_renderer.h
    engines/ags/shared/font/wfn_font_renderer.h


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 50fb9eef052..4b651da6c56 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -52,6 +52,7 @@
 #include "ags/engine/ac/system.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/engine/debugging/debug_log.h"
+#include "ags/shared/font/fonts.h"
 #include "ags/engine/gui/gui_dialog.h"
 #include "ags/engine/main/engine.h"
 #include "ags/engine/main/game_run.h"
@@ -425,6 +426,8 @@ int SetGameOption(int opt, int setting) {
 	} else if (opt == OPT_PORTRAITSIDE) {
 		if (setting == 0)  // set back to Left
 			_GP(play).swap_portrait_side = 0;
+	} else if (opt == OPT_ANTIALIASFONTS) {
+		adjust_fonts_for_render_mode(setting != 0);
 	}
 
 	return oldval;
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index e14e4ed5c57..f84772f92ff 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -43,6 +43,7 @@
 #include "ags/engine/debugging/debugger.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/device/mouse_w32.h"
+#include "ags/shared/font/fonts.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/engine/gfx/ddb.h"
 #include "ags/engine/gfx/graphics_driver.h"
@@ -598,6 +599,8 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	}
 	update_directional_sound_vol();
 
+	adjust_fonts_for_render_mode(_GP(game).options[OPT_ANTIALIASFONTS]);
+
 	recreate_overlay_ddbs();
 
 	GUI::MarkAllGUIForUpdate();
diff --git a/engines/ags/lib/alfont/alfont.cpp b/engines/ags/lib/alfont/alfont.cpp
index 1da914588e0..de18a0c425a 100644
--- a/engines/ags/lib/alfont/alfont.cpp
+++ b/engines/ags/lib/alfont/alfont.cpp
@@ -413,7 +413,7 @@ int alfont_set_font_size_ex(ALFONT_FONT *f, int h, int flags) {
 	int error, test_h, direction;
 	int real_height;
 	/* check the font doesn't already use that w and h */
-	if (h == f->face_h)
+	if ((h == f->face_h) && (flags & ALFONT_FLG_FORCE_RESIZE) == 0)
 		return ALFONT_OK;
 	else if (h <= 0)
 		return ALFONT_ERROR;
diff --git a/engines/ags/lib/alfont/alfont.h b/engines/ags/lib/alfont/alfont.h
index f22a2447fab..07cf53ba1cd 100644
--- a/engines/ags/lib/alfont/alfont.h
+++ b/engines/ags/lib/alfont/alfont.h
@@ -42,8 +42,10 @@ namespace AGS3 {
 
 /* font adjustment flags (AGS compatibility hacks) */
 
+// Force reupdate the font even if the face size matches the request
+#define ALFONT_FLG_FORCE_RESIZE       0x01
 // Make ascender equal to formal font height
-#define ALFONT_FLG_ASCENDER_EQ_HEIGHT 0x01
+#define ALFONT_FLG_ASCENDER_EQ_HEIGHT 0x02
 
 /* structs */
 typedef struct ALFONT_FONT ALFONT_FONT;
diff --git a/engines/ags/shared/font/ags_font_renderer.h b/engines/ags/shared/font/ags_font_renderer.h
index 6eb15e61bc3..379be3422a1 100644
--- a/engines/ags/shared/font/ags_font_renderer.h
+++ b/engines/ags/shared/font/ags_font_renderer.h
@@ -67,6 +67,8 @@ public:
 		FontMetrics *metrics) = 0;
 	// Gets font's name; must return an empty string if no name is available
 	virtual const char *GetName(int fontNumber) = 0;
+	// Perform any necessary adjustments when the AA mode is toggled
+	virtual void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) = 0;
 protected:
 	IAGSFontRenderer2() {}
 	~IAGSFontRenderer2() {}
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index b65b7f87eae..60dbc86c4c3 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -455,6 +455,13 @@ void alloc_font_outline_buffers(size_t font_number,
 	*outline_stencil = &f.OutlineStencilSub;
 }
 
+void adjust_fonts_for_render_mode(bool aa_mode) {
+	for (size_t i = 0; i < _GP(fonts).size(); ++i) {
+		if (_GP(fonts)[i].Renderer2 != nullptr)
+			_GP(fonts)[i].Renderer2->AdjustFontForAntiAlias(i, aa_mode);
+	}
+}
+
 void wfreefont(size_t fontNumber) {
 	if (fontNumber >= _GP(fonts).size())
 		return;
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index 84cd5ca8dfd..32d898d7775 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -135,6 +135,8 @@ void wgtprintf(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t
 void alloc_font_outline_buffers(size_t font_number,
 	Shared::Bitmap **text_stencil, Shared::Bitmap **outline_stencil,
 	int text_width, int text_height, int color_depth);
+// Perform necessary adjustments on all fonts in case the text render mode changed (anti-aliasing etc)
+void adjust_fonts_for_render_mode(bool aa_mode);
 // Free particular font's data
 void wfreefont(size_t fontNumber);
 // Free all fonts data
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index 9d8b0369cac..156ddbb62ec 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -78,6 +78,16 @@ bool TTFFontRenderer::IsBitmapFont() {
 	return false;
 }
 
+static int GetAlfontFlags() {
+	int flags = ALFONT_FLG_FORCE_RESIZE;
+	// Compatibility: font ascender is always adjusted to the formal font's height;
+	// EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing
+	// (the reason is uncertain, but this is to emulate old engine's behavior).
+	if (!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
+		flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT;
+	return flags;
+}
+
 bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	const FontRenderParams *params, FontMetrics *metrics) {
 	String file_name = String::FromFormat("agsfnt%d.ttf", fontNumber);
@@ -102,13 +112,8 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 		fontSize = 8; // compatibility fix
 	if (params && params->SizeMultiplier > 1)
 		fontSize *= params->SizeMultiplier;
-	// Compatibility: font ascender is always adjusted to the formal font's height;
-	// EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing
-	// (the reason is uncertain, but this is to emulate old engine's behavior).
-	int alfont_flags = 0;
-	if (!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
-		alfont_flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT;
-	alfont_set_font_size_ex(alfptr, fontSize, alfont_flags);
+
+	alfont_set_font_size_ex(alfptr, fontSize, GetAlfontFlags());
 
 	_fontData[fontNumber].AlFont = alfptr;
 	_fontData[fontNumber].Params = params ? *params : FontRenderParams();
@@ -116,7 +121,7 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	if (metrics) {
 		metrics->Height = alfont_get_font_height(alfptr);
 		metrics->RealHeight = alfont_get_font_real_height(alfptr);
-}
+	}
 	return true;
 }
 
@@ -124,6 +129,14 @@ const char *TTFFontRenderer::GetName(int fontNumber) {
 	return alfont_get_name(_fontData[fontNumber].AlFont);
 }
 
+void TTFFontRenderer::AdjustFontForAntiAlias(int fontNumber, bool aa_mode) {
+	if (_G(loaded_game_file_version) < kGameVersion_341) {
+		ALFONT_FONT *alfptr = _fontData[fontNumber].AlFont;
+		int old_height = alfont_get_font_height(alfptr);
+		alfont_set_font_size_ex(alfptr, old_height, GetAlfontFlags());
+	}
+}
+
 void TTFFontRenderer::FreeMemory(int fontNumber) {
 	alfont_destroy_font(_fontData[fontNumber].AlFont);
 	_fontData.erase(fontNumber);
diff --git a/engines/ags/shared/font/ttf_font_renderer.h b/engines/ags/shared/font/ttf_font_renderer.h
index 80a30b492dc..1b2e7bedf51 100644
--- a/engines/ags/shared/font/ttf_font_renderer.h
+++ b/engines/ags/shared/font/ttf_font_renderer.h
@@ -50,6 +50,7 @@ public:
 	bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
 		FontMetrics *metrics) override;
 	const char *GetName(int fontNumber) override;
+	void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) override;
 
 private:
 	struct FontData {
diff --git a/engines/ags/shared/font/wfn_font_renderer.h b/engines/ags/shared/font/wfn_font_renderer.h
index 13600faf736..de01ce2ead1 100644
--- a/engines/ags/shared/font/wfn_font_renderer.h
+++ b/engines/ags/shared/font/wfn_font_renderer.h
@@ -48,6 +48,7 @@ public:
 	bool LoadFromDiskEx(int fontNumber, int fontSize,
 		const FontRenderParams *params, FontMetrics *metrics) override;
 	const char *GetName(int fontNumber) override { return ""; }
+	void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) override { /* do nothing */ }
 
 private:
 	struct FontData {


Commit: 5b10b7437cd11006045d5c3b1be8a697afc887b3
    https://github.com/scummvm/scummvm/commit/5b10b7437cd11006045d5c3b1be8a697afc887b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:14-07:00

Commit Message:
AGS: Added "ascender fixup" flag to the font init mode

SHA-1: 1273e64c1b82ffbcbbc90261952b6192bef9c966

Changed paths:
    engines/ags/shared/ac/game_version.h
    engines/ags/shared/font/ags_font_renderer.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/fonts.h
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/game/main_game_file.cpp


diff --git a/engines/ags/shared/ac/game_version.h b/engines/ags/shared/ac/game_version.h
index 37acb875118..fbc7a3665e7 100644
--- a/engines/ags/shared/ac/game_version.h
+++ b/engines/ags/shared/ac/game_version.h
@@ -116,7 +116,8 @@ Option to allow legacy relative asset resolutions.
 3.6.0 :
 Format value is defined as AGS version represented as NN,NN,NN,NN.
 Fonts have adjustable outline
-
+3.6.0.11:
+Font load flags, control backward compatible font behavior
 */
 
 enum GameDataVersion {
@@ -150,7 +151,8 @@ enum GameDataVersion {
 	kGameVersion_341_2 = 49,
 	kGameVersion_350 = 50,
 	kGameVersion_360 = 3060000,
-	kGameVersion_Current = kGameVersion_360
+	kGameVersion_360_11 = 3060011,
+	kGameVersion_Current = kGameVersion_360_11
 };
 
 } // namespace AGS3
diff --git a/engines/ags/shared/font/ags_font_renderer.h b/engines/ags/shared/font/ags_font_renderer.h
index 379be3422a1..e2479093762 100644
--- a/engines/ags/shared/font/ags_font_renderer.h
+++ b/engines/ags/shared/font/ags_font_renderer.h
@@ -48,6 +48,7 @@ protected:
 struct FontRenderParams {
 	// Font's render multiplier
 	int SizeMultiplier = 1;
+	int LoadMode = 0;
 };
 
 // Describes loaded font's properties
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index 60dbc86c4c3..122dde9c0cc 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -85,7 +85,7 @@ static void post_init_font(size_t fontNumber, int load_mode) {
 		font.Metrics.Height = height;
 		font.Metrics.RealHeight = height;
 	}
-	font.Metrics.CompatHeight = (load_mode & FONT_LOAD_REPORTREALHEIGHT) == 0 ?
+	font.Metrics.CompatHeight = (load_mode & FONT_LOAD_REPORTNOMINALHEIGHT) != 0 ?
 		font.Metrics.Height : font.Metrics.RealHeight;
 
 	if (font.Info.Outline != FONT_OUTLINE_AUTO) {
@@ -97,13 +97,12 @@ static void post_init_font(size_t fontNumber, int load_mode) {
 	font.LineSpacingCalc = font.Info.LineSpacing;
 	if (font.Info.LineSpacing == 0) {
 		font.Info.Flags |= FFLG_DEFLINESPACING;
-		const int height = font.Metrics.Height;
-		font.LineSpacingCalc = height + 2 * font.Info.AutoOutlineThickness;
-		// NOTE: we use formal font height to define default linespacing;
-		// this is compatible with the old games and also seem to give nicer
-		// looks (plus user may always setup custom linespacing).
-		// If real height will be wanted, check for FONT_LOAD_REPORTREALHEIGHT
-		// flag in "load_mode" to know when to apply real or formal height.
+		// Use either nominal or real pixel font height to define default linespacing;
+		// linespacing = nominal height is compatible with the old games
+		if ((load_mode & FONT_LOAD_REPORTNOMINALHEIGHT) == 0)
+			font.LineSpacingCalc = font.Metrics.RealHeight + 2 * font.Info.AutoOutlineThickness;
+		else
+			font.LineSpacingCalc = font.Metrics.Height + 2 * font.Info.AutoOutlineThickness;
 	}
 }
 
@@ -398,6 +397,7 @@ bool load_font_size(size_t fontNumber, const FontInfo &font_info, int load_mode)
 		wfreefont(fontNumber);
 	FontRenderParams params;
 	params.SizeMultiplier = font_info.SizeMultiplier;
+	params.LoadMode = load_mode;
 	FontMetrics metrics;
 
 	if (_GP(ttfRenderer).LoadFromDiskEx(fontNumber, font_info.SizePt, &params, &metrics)) {
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index 32d898d7775..c9aa7511a78 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -32,9 +32,14 @@
 namespace AGS3 {
 
 // Font load flags, primarily for backward compatibility
-// REPORTREALHEIGHT: get_font_height should return real font's height,
-// otherwise returns formal height, equal to "font size" parameter
-#define FONT_LOAD_REPORTREALHEIGHT 0x01
+// REPORTNOMINALHEIGHT: get_font_height should return nominal font's height,
+// eq to "font size" parameter, otherwise returns real pixel height.
+#define FONT_LOAD_REPORTNOMINALHEIGHT 0x01
+// ASCENDFIXUP: do the TTF ascender fixup, where font's ascender is resized
+// to the nominal font's height.
+#define FONT_LOAD_ASCENDERFIXUP       0x02
+// Collection of flags defining fully backward compatible TTF behavior
+#define FONT_LOAD_FULLBACKCOMPAT      (FONT_LOAD_REPORTNOMINALHEIGHT | FONT_LOAD_ASCENDERFIXUP)
 
 class IAGSFontRenderer;
 class IAGSFontRenderer2;
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index 156ddbb62ec..e7479f2a462 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -78,12 +78,13 @@ bool TTFFontRenderer::IsBitmapFont() {
 	return false;
 }
 
-static int GetAlfontFlags() {
+static int GetAlfontFlags(int load_mode) {
 	int flags = ALFONT_FLG_FORCE_RESIZE;
 	// Compatibility: font ascender is always adjusted to the formal font's height;
 	// EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing
 	// (the reason is uncertain, but this is to emulate old engine's behavior).
-	if (!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
+	if (((load_mode & FONT_LOAD_ASCENDERFIXUP) != 0) &&
+		!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
 		flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT;
 	return flags;
 }
@@ -113,7 +114,7 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	if (params && params->SizeMultiplier > 1)
 		fontSize *= params->SizeMultiplier;
 
-	alfont_set_font_size_ex(alfptr, fontSize, GetAlfontFlags());
+	alfont_set_font_size_ex(alfptr, fontSize, GetAlfontFlags(params->LoadMode));
 
 	_fontData[fontNumber].AlFont = alfptr;
 	_fontData[fontNumber].Params = params ? *params : FontRenderParams();
@@ -132,8 +133,9 @@ const char *TTFFontRenderer::GetName(int fontNumber) {
 void TTFFontRenderer::AdjustFontForAntiAlias(int fontNumber, bool aa_mode) {
 	if (_G(loaded_game_file_version) < kGameVersion_341) {
 		ALFONT_FONT *alfptr = _fontData[fontNumber].AlFont;
+		const FontRenderParams &params = _fontData[fontNumber].Params;
 		int old_height = alfont_get_font_height(alfptr);
-		alfont_set_font_size_ex(alfptr, old_height, GetAlfontFlags());
+		alfont_set_font_size_ex(alfptr, old_height, GetAlfontFlags(params.LoadMode));
 	}
 }
 
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 3a263992f15..7583039ed8c 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -842,6 +842,10 @@ HGameFileError UpdateGameData(LoadedGameEntities &ents, GameDataVersion data_ver
 	if (data_ver < kGameVersion_350) {
 		game.options[OPT_RELATIVEASSETRES] = 1;
 	}
+	// Pre-3.6.0.11 TTF fonts are always loaded in backward-compat mode
+	if (data_ver < kGameVersion_360_11) {
+		game.options[OPT_FONTLOADLOGIC] = FONT_LOAD_FULLBACKCOMPAT;
+	}
 	FixupSaveDirectory(game);
 	return HGameFileError::None();
 }


Commit: 84a54f5e8e52e37827273fd7a27625a1caf06833
    https://github.com/scummvm/scummvm/commit/84a54f5e8e52e37827273fd7a27625a1caf06833
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:14-07:00

Commit Message:
AGS: Remade OPT_FONTLOADLOGIC into individual font's flags

>From upstream 54c5303c5e0ed98609397d9e5df4114f128fb4a2

Changed paths:
    engines/ags/engine/game/game_init.cpp
    engines/ags/plugins/ags_plugin.cpp
    engines/ags/shared/ac/game_struct_defines.h
    engines/ags/shared/ac/game_version.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/fonts.h
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/game/main_game_file.cpp


diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 758e83ad8cc..d899185258e 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -261,7 +261,7 @@ HError InitAndRegisterGameEntities() {
 void LoadFonts(GameSetupStruct &game, GameDataVersion data_ver) {
 	for (int i = 0; i < _GP(game).numfonts; ++i) {
 		FontInfo &finfo = _GP(game).fonts[i];
-		if (!load_font_size(i, finfo, game.options[OPT_FONTLOADLOGIC]))
+		if (!load_font_size(i, finfo))
 			quitprintf("Unable to load font %d, no renderer could load a matching file", i);
 
 		const bool is_wfn = is_bitmap_font(i);
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index ea5724238ac..9b497229820 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -744,7 +744,7 @@ void IAGSEngine::BreakIntoDebugger() {
 }
 
 IAGSFontRenderer *IAGSEngine::ReplaceFontRenderer(int fontNumber, IAGSFontRenderer *newRenderer) {
-	auto *old_render = font_replace_renderer(fontNumber, newRenderer, _GP(game).options[OPT_FONTLOADLOGIC]);
+	auto *old_render = font_replace_renderer(fontNumber, newRenderer);
 	GUI::MarkForFontUpdate(fontNumber);
 	return old_render;
 }
diff --git a/engines/ags/shared/ac/game_struct_defines.h b/engines/ags/shared/ac/game_struct_defines.h
index a5f569b28f3..7c36950dc5c 100644
--- a/engines/ags/shared/ac/game_struct_defines.h
+++ b/engines/ags/shared/ac/game_struct_defines.h
@@ -85,7 +85,6 @@ namespace AGS3 {
 #define OPT_RENDERATSCREENRES 45 // scale sprites at the (final) screen resolution
 #define OPT_RELATIVEASSETRES 46 // relative asset resolution mode (where sprites are resized to match game type)
 #define OPT_WALKSPEEDABSOLUTE 47 // if movement speeds are independent of walkable mask resolution
-#define OPT_FONTLOADLOGIC   48 // fonts load/init logic, see FONT_LOAD_xxx flags
 #define OPT_HIGHESTOPTION   OPT_WALKSPEEDABSOLUTE
 #define OPT_NOMODMUSIC      98
 #define OPT_LIPSYNCTEXT     99
@@ -105,8 +104,19 @@ namespace AGS3 {
 #define FFLG_LEGACY_SIZEMASK 0x3f
 #define MAX_LEGACY_FONT_SIZE 63
 // Contemporary font flags
-#define FFLG_SIZEMULTIPLIER  0x01  // size data means multiplier
-#define FFLG_DEFLINESPACING  0x02  // linespacing derived from the font height
+#define FFLG_SIZEMULTIPLIER        0x01  // size data means multiplier
+#define FFLG_DEFLINESPACING        0x02  // linespacing derived from the font height
+// Font load flags, primarily for backward compatibility:
+// REPORTNOMINALHEIGHT: get_font_height should return nominal font's height,
+// eq to "font size" parameter, otherwise returns real pixel height.
+#define FFLG_REPORTNOMINALHEIGHT   0x04
+// ASCENDFIXUP: do the TTF ascender fixup, where font's ascender is resized
+// to the nominal font's height.
+#define FFLG_ASCENDERFIXUP         0x08
+// Collection of flags defining fully backward compatible TTF fixup
+#define FFLG_TTF_BACKCOMPATMASK   (FFLG_REPORTNOMINALHEIGHT | FFLG_ASCENDERFIXUP)
+// Collection of flags defining font's load mode
+#define FFLG_LOADMODEMASK         (FFLG_REPORTNOMINALHEIGHT | FFLG_ASCENDERFIXUP)
 // Font outline types
 #define FONT_OUTLINE_NONE -1
 #define FONT_OUTLINE_AUTO -10
diff --git a/engines/ags/shared/ac/game_version.h b/engines/ags/shared/ac/game_version.h
index fbc7a3665e7..8ccd1fd61ab 100644
--- a/engines/ags/shared/ac/game_version.h
+++ b/engines/ags/shared/ac/game_version.h
@@ -117,7 +117,8 @@ Option to allow legacy relative asset resolutions.
 Format value is defined as AGS version represented as NN,NN,NN,NN.
 Fonts have adjustable outline
 3.6.0.11:
-Font load flags, control backward compatible font behavior
+New font load flags, control backward compatible font behavior
+
 */
 
 enum GameDataVersion {
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index 122dde9c0cc..1ae62b329bf 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -73,7 +73,7 @@ bool is_font_loaded(size_t fontNumber) {
 }
 
 // Finish font's initialization
-static void post_init_font(size_t fontNumber, int load_mode) {
+static void font_post_init(size_t fontNumber) {
 	Font &font = _GP(fonts)[fontNumber];
 	if (font.Metrics.Height == 0) {
 		// There is no explicit method for getting maximal possible height of any
@@ -85,7 +85,9 @@ static void post_init_font(size_t fontNumber, int load_mode) {
 		font.Metrics.Height = height;
 		font.Metrics.RealHeight = height;
 	}
-	font.Metrics.CompatHeight = (load_mode & FONT_LOAD_REPORTNOMINALHEIGHT) != 0 ?
+	// Use either nominal or real pixel height to define font's logical height
+	// and default linespacing; logical height = nominal height is compatible with the old games
+	font.Metrics.CompatHeight = (font.Info.Flags & FFLG_REPORTNOMINALHEIGHT) != 0 ?
 		font.Metrics.Height : font.Metrics.RealHeight;
 
 	if (font.Info.Outline != FONT_OUTLINE_AUTO) {
@@ -96,23 +98,17 @@ static void post_init_font(size_t fontNumber, int load_mode) {
 	// default linespacing from the font height + outline thickness.
 	font.LineSpacingCalc = font.Info.LineSpacing;
 	if (font.Info.LineSpacing == 0) {
-		font.Info.Flags |= FFLG_DEFLINESPACING;
-		// Use either nominal or real pixel font height to define default linespacing;
-		// linespacing = nominal height is compatible with the old games
-		if ((load_mode & FONT_LOAD_REPORTNOMINALHEIGHT) == 0)
-			font.LineSpacingCalc = font.Metrics.RealHeight + 2 * font.Info.AutoOutlineThickness;
-		else
-			font.LineSpacingCalc = font.Metrics.Height + 2 * font.Info.AutoOutlineThickness;
+		font.LineSpacingCalc = font.Metrics.CompatHeight + 2 * font.Info.AutoOutlineThickness;
 	}
 }
 
-IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer, int load_mode) {
+IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer) {
 	if (fontNumber >= _GP(fonts).size())
 		return nullptr;
 	IAGSFontRenderer *oldRender = _GP(fonts)[fontNumber].Renderer;
 	_GP(fonts)[fontNumber].Renderer = renderer;
 	_GP(fonts)[fontNumber].Renderer2 = nullptr;
-	post_init_font(fontNumber, load_mode);
+	font_post_init(fontNumber);
 	return oldRender;
 }
 
@@ -379,8 +375,10 @@ void wouttextxy(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t
 }
 
 void set_fontinfo(size_t fontNumber, const FontInfo &finfo) {
-	if (fontNumber < _GP(fonts).size() && _GP(fonts)[fontNumber].Renderer)
+	if (fontNumber < _GP(fonts).size() && _GP(fonts)[fontNumber].Renderer) {
 		_GP(fonts)[fontNumber].Info = finfo;
+		font_post_init(fontNumber);
+	}
 }
 
 FontInfo get_fontinfo(size_t font_number) {
@@ -390,14 +388,14 @@ FontInfo get_fontinfo(size_t font_number) {
 }
 
 // Loads a font from disk
-bool load_font_size(size_t fontNumber, const FontInfo &font_info, int load_mode) {
+bool load_font_size(size_t fontNumber, const FontInfo &font_info) {
 	if (_GP(fonts).size() <= fontNumber)
 		_GP(fonts).resize(fontNumber + 1);
 	else
 		wfreefont(fontNumber);
 	FontRenderParams params;
 	params.SizeMultiplier = font_info.SizeMultiplier;
-	params.LoadMode = load_mode;
+	params.LoadMode = (font_info.Flags & FFLG_LOADMODEMASK);
 	FontMetrics metrics;
 
 	if (_GP(ttfRenderer).LoadFromDiskEx(fontNumber, font_info.SizePt, &params, &metrics)) {
@@ -413,7 +411,7 @@ bool load_font_size(size_t fontNumber, const FontInfo &font_info, int load_mode)
 
 	_GP(fonts)[fontNumber].Info = font_info;
 	_GP(fonts)[fontNumber].Metrics = metrics;
-	post_init_font(fontNumber, load_mode);
+	font_post_init(fontNumber);
 	return true;
 }
 
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index c9aa7511a78..751e869ebd5 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -31,16 +31,6 @@
 
 namespace AGS3 {
 
-// Font load flags, primarily for backward compatibility
-// REPORTNOMINALHEIGHT: get_font_height should return nominal font's height,
-// eq to "font size" parameter, otherwise returns real pixel height.
-#define FONT_LOAD_REPORTNOMINALHEIGHT 0x01
-// ASCENDFIXUP: do the TTF ascender fixup, where font's ascender is resized
-// to the nominal font's height.
-#define FONT_LOAD_ASCENDERFIXUP       0x02
-// Collection of flags defining fully backward compatible TTF behavior
-#define FONT_LOAD_FULLBACKCOMPAT      (FONT_LOAD_REPORTNOMINALHEIGHT | FONT_LOAD_ASCENDERFIXUP)
-
 class IAGSFontRenderer;
 class IAGSFontRenderer2;
 struct FontInfo;
@@ -78,7 +68,7 @@ struct FontRenderParams;
 void init_font_renderer();
 void shutdown_font_renderer();
 void adjust_y_coordinate_for_text(int *ypos, size_t fontnum);
-IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer, int load_mode);
+IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer);
 bool font_first_renderer_loaded();
 bool is_font_loaded(size_t fontNumber);
 bool is_bitmap_font(size_t fontNumber);
@@ -133,8 +123,7 @@ void set_fontinfo(size_t fontNumber, const FontInfo &finfo);
 // Gets full information about the font
 FontInfo get_fontinfo(size_t font_number);
 // Loads a font from disk
-bool load_font_size(size_t fontNumber, const FontInfo &font_info, int load_mode);
-void wgtprintf(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t text_color, char *fmt, ...);
+bool load_font_size(size_t fontNumber, const FontInfo &font_info); void wgtprintf(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t text_color, char *fmt, ...);
 // Allocates two outline stencil buffers, or returns previously creates ones;
 // these buffers are owned by the font, they should not be deleted by the caller.
 void alloc_font_outline_buffers(size_t font_number,
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index e7479f2a462..4285de26aab 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -83,7 +83,7 @@ static int GetAlfontFlags(int load_mode) {
 	// Compatibility: font ascender is always adjusted to the formal font's height;
 	// EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing
 	// (the reason is uncertain, but this is to emulate old engine's behavior).
-	if (((load_mode & FONT_LOAD_ASCENDERFIXUP) != 0) &&
+	if (((load_mode & FFLG_ASCENDERFIXUP) != 0) &&
 		!(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341)))
 		flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT;
 	return flags;
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 7583039ed8c..b5c465a510c 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -488,6 +488,11 @@ void UpgradeFonts(GameSetupStruct &game, GameDataVersion data_ver) {
 			}
 		}
 	}
+	if (data_ver < kGameVersion_360_11) { // use global defaults for the font load flags
+		for (int i = 0; i < game.numfonts; ++i) {
+			game.fonts[i].Flags |= FFLG_TTF_BACKCOMPATMASK;
+		}
+	}
 }
 
 // Convert audio data to the current version
@@ -842,10 +847,6 @@ HGameFileError UpdateGameData(LoadedGameEntities &ents, GameDataVersion data_ver
 	if (data_ver < kGameVersion_350) {
 		game.options[OPT_RELATIVEASSETRES] = 1;
 	}
-	// Pre-3.6.0.11 TTF fonts are always loaded in backward-compat mode
-	if (data_ver < kGameVersion_360_11) {
-		game.options[OPT_FONTLOADLOGIC] = FONT_LOAD_FULLBACKCOMPAT;
-	}
 	FixupSaveDirectory(game);
 	return HGameFileError::None();
 }


Commit: 4005849cf07108ce04bca0a8bc5390520456b5d5
    https://github.com/scummvm/scummvm/commit/4005849cf07108ce04bca0a8bc5390520456b5d5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T13:37:14-07:00

Commit Message:
AGS: Updated build version (3.6.0.11)

>From upstream ecf803c050b08554025e9676188f52a4e78c532b

Changed paths:
    engines/ags/shared/core/def_version.h


diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 99d10a9aefe..048b4e44617 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
 #ifndef AGS_SHARED_CORE_DEFVERSION_H
 #define AGS_SHARED_CORE_DEFVERSION_H
 
-#define ACI_VERSION_STR      "3.6.0.10"
+#define ACI_VERSION_STR      "3.6.0.11"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3.6.0.10
+#define ACI_VERSION_MSRC_DEF  3.6.0.11
 #endif
 
 #define SPECIAL_VERSION ""


Commit: 3395af886f9750b6988ed45645376763a47a1494
    https://github.com/scummvm/scummvm/commit/3395af886f9750b6988ed45645376763a47a1494
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-27T14:00:51-07:00

Commit Message:
COMMON: Fix assert crash trying to open invalid fs nodes

It was previously trying to print out the node path,
which was asserting because the node wasn't valid

Changed paths:
    common/file.cpp


diff --git a/common/file.cpp b/common/file.cpp
index 865c494dfc5..ca8ab78c662 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -62,7 +62,7 @@ bool File::open(const FSNode &node) {
 	assert(!_handle);
 
 	if (!node.exists()) {
-		warning("File::open: '%s' does not exist", node.getPath().c_str());
+		warning("File::open: node does not exist");
 		return false;
 	} else if (node.isDirectory()) {
 		warning("File::open: '%s' is a directory", node.getPath().c_str());




More information about the Scummvm-git-logs mailing list