/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
// Following are pulled in for wchar.h header on XCode iOS-7
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_fgetwc
#define FORBIDDEN_SYMBOL_EXCEPTION_fgetws
#define FORBIDDEN_SYMBOL_EXCEPTION_asctime
#define FORBIDDEN_SYMBOL_EXCEPTION_clock
#define FORBIDDEN_SYMBOL_EXCEPTION_ctime
#define FORBIDDEN_SYMBOL_EXCEPTION_difftime
#define FORBIDDEN_SYMBOL_EXCEPTION_getdate
#define FORBIDDEN_SYMBOL_EXCEPTION_gmtime
#define FORBIDDEN_SYMBOL_EXCEPTION_localtime
#define FORBIDDEN_SYMBOL_EXCEPTION_mktime
#define FORBIDDEN_SYMBOL_EXCEPTION_time
#include "common/scummsys.h"
#ifdef USE_FREETYPE2
#include
#include "ags/lib/alfont/alfont.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 "graphics/fonts/freetype.h"
#ifndef NO_FT213_AUTOHINT
#include "ags/lib/freetype-2.1.3/autohint/ahhint.h"
#endif
namespace AGS3 {
using Graphics::FreeType::Init_FreeType;
using Graphics::FreeType::Init_FreeType_With_Mem;
using Graphics::FreeType::Done_FreeType;
using Graphics::FreeType::Done_FreeType_With_Mem;
using Graphics::FreeType::Load_Glyph;
using Graphics::FreeType::Get_Glyph;
using Graphics::FreeType::Glyph_Copy;
using Graphics::FreeType::Glyph_To_Bitmap;
using Graphics::FreeType::Done_Glyph;
using Graphics::FreeType::Set_Pixel_Sizes;
using Graphics::FreeType::New_Face;
using Graphics::FreeType::New_Memory_Face;
using Graphics::FreeType::Done_Face;
using Graphics::FreeType::Get_Char_Index;
using Graphics::FreeType::Get_Kerning;
#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 */
int real_face_extent_asc; /* calculated max extent of glyphs (ascender) */
int real_face_extent_desc; /* calculated max extent of glyphs (descender) */
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;
static FT_Memory ft_memory;
#ifndef NO_FT213_AUTOHINT
static FreeType213::AH_Hinter ft_hinter;
#endif
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 */
uint32_t __skiptranspixels_blender_trans15(uint32_t x, uint32_t y, uint32_t n) {
uint32_t 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 */
uint32_t __skiptranspixels_blender_trans16(uint32_t x, uint32_t y, uint32_t n) {
uint32_t 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 */
uint32_t __preservedalpha_blender_trans24(uint32_t x, uint32_t y, uint32_t n) {
uint32_t 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) {
// TODO: The current putpixel() implementation does not support blending in DRAW_MODE_TRANS mode (which is not implemented),
// so we can't just call set_blender_mode() here.
// The actual blending is done by the apply_trans_blender() function, just before the putpixel() calls
//set_blender_mode(__skiptranspixels_blender_trans15, __skiptranspixels_blender_trans16, __preservedalpha_blender_trans24, r, g, b, a);
//set_blender_mode(kAlphaPreservedBlenderMode, r, g, b, a);
}
/* blends a pixel using the alternative blenders, this is a replacement
* for the previous function using set_blender_mode
*/
int apply_trans_blender(BITMAP *bmp, int color1, int color2, int alpha) {
switch (bitmap_color_depth(bmp)) {
case 15:
return __skiptranspixels_blender_trans15(color1, color2, alpha);
case 16:
return __skiptranspixels_blender_trans16(color1, color2, alpha);
case 24:
case 32:
return __preservedalpha_blender_trans24(color1, color2, alpha);
default:
return color1;
}
}
/* 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 ((glyph_number < 0) || (glyph_number >= f->face->num_glyphs))
return;
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_number < 0) || (glyph_number >= f->face->num_glyphs))
return;
/* if glyph not cached yet */
if (!f->cached_glyphs[glyph_number].is_cached) {
FT_Glyph new_glyph;
/* load the font glyph */
#ifdef NO_FT213_AUTOHINT
Load_Glyph(f->face, glyph_number, FT_LOAD_DEFAULT);
#else
FT_Int32 load_flags = FT_LOAD_DEFAULT;
FT_GlyphSlot slot = f->face->glyph;
FreeType213::ah_hinter_load_glyph(ft_hinter, slot, f->face->size, glyph_number, FT_LOAD_DEFAULT);
/* compute the advance */
if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
slot->advance.x = 0;
slot->advance.y = slot->metrics.vertAdvance;
} else {
slot->advance.x = slot->metrics.horiAdvance;
slot->advance.y = 0;
}
/* compute the linear advance in 16.16 pixels */
if ((load_flags & FT_LOAD_LINEAR_DESIGN) == 0) {
FT_UInt EM = f->face->units_per_EM;
FT_Size_Metrics *metrics = &f->face->size->metrics;
slot->linearHoriAdvance = FT_MulDiv(slot->linearHoriAdvance, (FT_Long)metrics->x_ppem << 16, EM);
slot->linearVertAdvance = FT_MulDiv(slot->linearVertAdvance, (FT_Long)metrics->y_ppem << 16, EM);
}
#endif
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;
Glyph_Copy(new_glyph, &glyph);
/* only render glyph if it is not already a bitmap */
if (glyph->format != ft_glyph_format_bitmap)
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;
}
}
}
Done_Glyph(glyph);
}
/* render the aa bmp */
{
FT_Bitmap *ft_bmp;
FT_Glyph glyph;
FT_BitmapGlyph bmp_glyph;
Glyph_Copy(new_glyph, &glyph);
/* only render glyph if it is not already a bitmap */
if (glyph->format != ft_glyph_format_bitmap)
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;
}
}
}
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 */
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;
}
}
static void _alfont_calculate_max_cbox(ALFONT_FONT *f, int max_glyphs) {
(void) max_glyphs; // kept just in case, but this was used to load N glyphs
FT_Long bbox_ymin = FT_MulFix(FT_DivFix(f->face->bbox.yMin, f->face->units_per_EM), f->face->size->metrics.y_ppem);
FT_Long bbox_ymax = FT_MulFix(FT_DivFix(f->face->bbox.yMax, f->face->units_per_EM), f->face->size->metrics.y_ppem);
f->real_face_extent_asc = (int)bbox_ymax;
f->real_face_extent_desc = -(int)bbox_ymin;
}
/* 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;
/* check the font doesn't already use that w and h */
if ((h == f->face_h) && (flags & ALFONT_FLG_FORCE_RESIZE) == 0)
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 = 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
if ((flags & ALFONT_FLG_SELECT_NOMINAL_SZ) != 0)
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
direction = 1;
}
/* check we didn't overpass it */
else if ((direction > 0) && (real_height > h)) {
/* decrease one and found */
test_h--;
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 = test_h;
f->real_face_h = real_height;
f->face_ascender = f->face->size->metrics.ascender >> 6;
/* Precalculate actual glyphs vertical extent */
if ((flags & ALFONT_FLG_PRECALC_MAX_CBOX) != 0) {
_alfont_calculate_max_cbox(f, 256);
}
/* AGS COMPAT HACK: set ascender to the formal font height */
if ((flags & ALFONT_FLG_ASCENDER_EQ_HEIGHT) != 0) {
f->face_ascender = test_h;
f->real_face_h = test_h + abs(f->face->size->metrics.descender >> 6);
}
return ALFONT_OK;
} else {
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;
}
ALFONT_DLL_DECLSPEC void alfont_get_font_real_vextent(ALFONT_FONT *f, int *top, int *bottom) {
*top = f->face_ascender - f->real_face_extent_asc; // may be negative
*bottom = f->face_ascender + f->real_face_extent_desc;
}
void alfont_exit(void) {
if (alfont_inited) {
alfont_inited = 0;
#ifndef NO_FT213_AUTOHINT
FreeType213::ah_hinter_done(ft_hinter);
#endif
Done_FreeType_With_Mem(ft_library, ft_memory);
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 = Init_FreeType_With_Mem(&ft_library, &ft_memory);
if (!error) {
#ifndef NO_FT213_AUTOHINT
error = FreeType213::ah_hinter_new(ft_memory, &ft_hinter);
if (error) {
Done_FreeType_With_Mem(ft_library, ft_memory);
}
#endif
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 = 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, (const void *)data, data_len);
/* load the font */
error = 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 */
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);
}
//#define APPLY_FONT_KERNING
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 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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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)) {
if(s_pointer) free(s_pointer);
s_pointer = NULL;
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);
#ifdef APPLY_FONT_KERNING
int last_glyph_index = 0;
#endif
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(&lpszW_tmp); character != 0; character = ugetxc(&lpszW_tmp), character = ugetxc(&lpszW_tmp)) {
#else
for (character = ugetxc(&lpszW_tmp); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index_tmp = character;
/* if out of existing glyph range -- skip it */
if ((glyph_index_tmp < 0) || (glyph_index_tmp >= f->face->num_glyphs))
continue;
/* 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(&lpszW); character != 0; character = ugetxc(&lpszW), character = ugetxc(&lpszW)) {
#else
for (character = ugetxc(&lpszW); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index = character;
/* if out of existing glyph range -- skip it */
if ((glyph_index < 0) || (glyph_index >= f->face->num_glyphs))
continue;
/* 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 */
#ifdef APPLY_FONT_KERNING
if (last_glyph_index) {
FT_Vector v;
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;
#endif
/* 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++;
const int orig_color = color;
if (alpha) {
if (alpha >= 255)
solid_mode();
else {
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
set_preservedalpha_trans_blender(0, 0, 0, alpha);
// apply blending
color = apply_trans_blender(bmp, color, getpixel(bmp, bmp_x, bmp_y), 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);
}
}
if (color != orig_color) // restore original color
color = orig_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;
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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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)) {
if(s_pointer) free(s_pointer);
s_pointer = NULL;
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);
#ifdef APPLY_FONT_KERNING
int last_glyph_index = 0;
#endif
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(&lpszW_tmp); character != 0; character = ugetxc(&lpszW_tmp), character = ugetxc(&lpszW_tmp)) {
#else
for (character = ugetxc(&lpszW_tmp); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index_tmp = character;
/* if out of existing glyph range -- skip it */
if ((glyph_index_tmp < 0) || (glyph_index_tmp >= f->face->num_glyphs))
continue;
/* 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(&lpszW); character != 0; character = ugetxc(&lpszW), character = ugetxc(&lpszW)) {
#else
for (character = ugetxc(&lpszW); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index = character;
/* if out of existing glyph range -- skip it */
if ((glyph_index < 0) || (glyph_index >= f->face->num_glyphs))
continue;
/* 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 */
#ifdef APPLY_FONT_KERNING
if (last_glyph_index) {
FT_Vector v;
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;
#endif
/* 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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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(&lpszW_tmp); character != 0; character = ugetxc(&lpszW_tmp), character = ugetxc(&lpszW_tmp)) {
#else
for (character = ugetxc(&lpszW_tmp); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index_tmp = character;
/* if out of existing glyph range -- skip it */
if ((glyph_index_tmp < 0) || (glyph_index_tmp >= f->face->num_glyphs))
continue;
/* 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(&lpszW); character != 0; character = ugetxc(&lpszW), character = ugetxc(&lpszW)) {
#else
for (character = ugetxc(&lpszW); character != 0; character = ugetxc(&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 = Get_Char_Index(f->face, character);
else
glyph_index = character;
/* apply kerning */
/*if (last_glyph_index) {
FT_Vector v;
Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
total_length += v.x >> 6;
}*/
last_glyph_index = glyph_index;
/* if out of existing glyph range -- skip it */
if ((glyph_index < 0) || (glyph_index >= f->face->num_glyphs))
continue;
/* 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 = Get_Char_Index(f->face, character);
else
glyph_index = character;
/* apply kerning */
/*if (last_glyph_index) {
FT_Vector v;
Get_Kerning(f->face, last_glyph_index, glyph_index, ft_kerning_default, &v);
total_length += v.x >> 6;
}*/
last_glyph_index = glyph_index;
/* if out of existing glyph range -- imagine empty char */
if ((glyph_index < 0) || (glyph_index >= f->face->num_glyphs))
return 0;
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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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(s);
#ifdef ALFONT_LINUX
ugetxc(s);
#endif
} else if (f->type == 2) {
ugetxc(&lpszWS);
#ifdef ALFONT_LINUX
ugetxc(&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(s);
#ifdef ALFONT_LINUX
ugetxc(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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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(s);
#ifdef ALFONT_LINUX
ugetxc(s);
#endif
} else if (f->type == 2) {
ugetxc(&lpszWS);
#ifdef ALFONT_LINUX
ugetxc(&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);
}
}
#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
if (str == NULL) {
return FALSE;
}
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);
snprintf(precedingchar_pointer, 2 * sizeof(char), "%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);
}
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_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);
}
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);
}
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_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);
}
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);
}
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);
}
}
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;
}
void alfont_set_precedingchar(ALFONT_FONT * f, int precedingchar) {
f->precedingchar = precedingchar;
}
int alfont_get_precedingchar(ALFONT_FONT * f) {
return f->precedingchar;
}
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
#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_set_font_size_ex(ALFONT_FONT *f, int h, int flags) { return 0; }
int alfont_get_font_height(ALFONT_FONT *f) { return 0; }
int alfont_get_font_real_height(ALFONT_FONT *f) { return 0; }
void alfont_get_font_real_vextent(ALFONT_FONT *f, int *top, int *bottom) { *top = 0; *bottom = 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