[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, ¶ms, &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 ¶ms = _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, ¶ms, &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