diff --git a/CMakeLists.txt b/CMakeLists.txt index 03f6f50..1552961 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ else() endif() optional_pkg_check_modules(SDL2MIXER IMPORTED_TARGET SDL2_mixer) + optional_pkg_check_modules(SDL2TTF IMPORTED_TARGET SDL2_ttf) endif() @@ -204,6 +205,11 @@ if (FREETYPE_FOUND) list(APPEND SUMMARY_FONT "freetype2") set(ENABLE_FT2 1) endif() +if (NOT X11_FOUND AND SDL2TTF_FOUND) + list(APPEND SRC_FONT font_sdlttf.c) + list(APPEND SUMMARY_FONT "SDL_ttf") + set(ENABLE_SDLTTF 1) +endif() if (NOT SRC_FONT) message(FATAL_ERROR "*** No font device available ***") endif() diff --git a/config.h.in b/config.h.in index f6c690c..2e1dcdb 100644 --- a/config.h.in +++ b/config.h.in @@ -19,6 +19,7 @@ #cmakedefine ENABLE_NLS @ENABLE_NLS@ #cmakedefine ENABLE_SDL @ENABLE_SDL@ #cmakedefine ENABLE_SDLMIXER @ENABLE_SDLMIXER@ +#cmakedefine ENABLE_SDLTTF @ENABLE_SDLTTF@ #cmakedefine ENABLE_X11FONT @ENABLE_X11FONT@ #cmakedefine CDROM_DEVICE "@CDROM_DEVICE@" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2a1123..8b67cd7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -97,6 +97,9 @@ else() # non-emscripten if (SDL2MIXER_FOUND) target_link_libraries(xsystem35 PRIVATE PkgConfig::SDL2MIXER) endif() + if (SDL2TTF_FOUND) + target_link_libraries(xsystem35 PRIVATE PkgConfig::SDL2TTF) + endif() install(TARGETS xsystem35 RUNTIME DESTINATION bin) endif() diff --git a/src/font.c b/src/font.c index 030143e..524ef66 100644 --- a/src/font.c +++ b/src/font.c @@ -43,6 +43,11 @@ void font_init(int dev) { case FONT_FT2: nact->ags.font = font_ft2_new(); break; +#endif +#ifdef ENABLE_SDLTTF + case FONT_SDLTTF: + nact->ags.font = font_sdlttf_new(); + break; #endif default: #ifndef ENABLE_SDL diff --git a/src/font_sdlttf.c b/src/font_sdlttf.c index fc9160c..cd53678 100644 --- a/src/font_sdlttf.c +++ b/src/font_sdlttf.c @@ -1,11 +1,15 @@ #include "config.h" +#include +#include #include #include #include "portab.h" #include "system.h" #include "font.h" +#include "sdl_private.h" +#include "utfsjis.h" typedef struct { int size; @@ -17,14 +21,14 @@ typedef struct { static FontTable fonttbl[FONTTABLEMAX]; static int fontcnt = 0; -static TTF_Font *fontset; +static FontTable *fontset; static FONT *this; -static void font_insert(int size, int type, ttfont *fontset) { +static void font_insert(int size, int type, TTF_Font *font) { fonttbl[fontcnt].size = size; fonttbl[fontcnt].type = type; - fonttbl[fontcnt].id = fontset; + fonttbl[fontcnt].id = font; if (fontcnt >= (FONTTABLEMAX -1)) { WARNING("Font table is full.\n"); @@ -44,14 +48,14 @@ static FontTable *font_lookup(int size, int type) { return NULL; } -static void font_ttf_sel_font(int type, int size) { +static void font_sdlttf_sel_font(int type, int size) { FontTable *tbl; if (NULL == (tbl = font_lookup(size, type))) { TTF_Font *fs; - fs = TTF_OpenFont(this->name[type], size); + fs = TTF_OpenFontIndex(this->name[type], size, this->face[type]); if (fs == NULL) { WARNING("%s is not found:\n", this->name[type]); @@ -59,38 +63,89 @@ static void font_ttf_sel_font(int type, int size) { } font_insert(size, type, fs); - fontset = fs; + fontset = &fonttbl[fontcnt - 1]; } else { - fontset = tbl->id; + fontset = tbl; } } static void *font_sdlttf_get_glyph(unsigned char *msg) { + return NULL; +} + +// SDL can't blit ARGB to an indexed bitmap properly, so we do it ourselves. +static void sdl_drawAntiAlias_8bpp(int dstx, int dsty, SDL_Surface *src, unsigned long col) +{ + SDL_LockSurface(sdl_dib); + + Uint8 cache[256*7]; + memset(cache, 0, 256); + + for (int y = 0; y < src->h && dsty + y < sdl_dib->h; y++) { + BYTE *sp = (BYTE*)src->pixels + y * src->pitch; + BYTE *dp = (BYTE*)sdl_dib->pixels + (dsty + y) * sdl_dib->pitch + dstx; + for (int x = 0; x < src->w && dstx + x < sdl_dib->w; x++) { + Uint8 r, g, b, alpha; + SDL_GetRGBA(*((Uint32*)sp), src->format, &r, &g, &b, &alpha); + alpha = alpha >> 5; // reduce bit depth + if (!alpha) { + // Transparent, do nothing + } else if (alpha == 7) { + *dp = col; // Fully opaque + } else if (cache[*dp] & 1 << alpha) { + *dp = cache[alpha << 8 | *dp]; // use cached value + } else { + // find nearest color in palette + cache[*dp] |= 1 << alpha; + int c = sdl_nearest_color( + (sdl_col[col].r * alpha + sdl_col[*dp].r * (7 - alpha)) / 7, + (sdl_col[col].g * alpha + sdl_col[*dp].g * (7 - alpha)) / 7, + (sdl_col[col].b * alpha + sdl_col[*dp].b * (7 - alpha)) / 7); + cache[alpha << 8 | *dp] = c; + *dp = c; + } + sp += src->format->BytesPerPixel; + dp++; + } + } + + SDL_UnlockSurface(sdl_dib); } static int font_sdlttf_draw_glyph(int x, int y, unsigned char *str, int cl) { SDL_Surface *fs; - SDL_Color fg; SDL_Rect r_src, r_dst; - int w, h; + int w, h, maxy; + BYTE *conv; - fg = SDL_MapRGB(sdl_dib->format, - sdl_col[cl].r, sdl_col[cl].g, sdl_col[cl].b); + if (!*str) + return 0; + conv = sjis2lang(str); if (this->antialiase_on) { - fs = TTF_RenderText_Shaded(fontset, str, cl); + fs = TTF_RenderUTF8_Blended(fontset->id, conv, sdl_col[cl]); } else { - fs = TTF_RenderText_Solid(fonset, str, cl); + fs = TTF_RenderText_Solid(fontset->id, conv, sdl_col[cl]); + } + if (!fs) { + WARNING("Text rendering failed: %s\n", TTF_GetError()); + free(conv); + return 0; } - TTF_SizeText(fontset, str, &w, &h); + TTF_SizeUTF8(fontset->id, conv, &w, &h); + y = max(0, y - (TTF_FontAscent(fontset->id) - fontset->size * 0.9)); - setRect(r_src, 0, 0, w, h); - setRect(r_dst, x, y, w, h); - - SDL_LockSurface(sdl_dib); - SDL_BlitSurface(fs, &r_src, sdl_dib, &r_dst); - SDL_UnlockSurface(sdl_dib); + if (sdl_dib->format->BitsPerPixel == 8 && this->antialiase_on) { + sdl_drawAntiAlias_8bpp(x, y, fs, cl); + } else { + setRect(r_src, 0, 0, w, h); + setRect(r_dst, x, y, w, h); + SDL_BlitSurface(fs, &r_src, sdl_dib, &r_dst); + } + + SDL_FreeSurface(fs); + free(conv); return w; } @@ -99,7 +154,7 @@ static boolean drawable() { return TRUE; } -FONT *font_ttf_new() { +FONT *font_sdlttf_new() { FONT *f = malloc(sizeof(FONT)); f->sel_font = font_sdlttf_sel_font; @@ -108,13 +163,12 @@ FONT *font_ttf_new() { f->self_drawable = drawable; f->antialiase_on = FALSE; - for (i = 0; i < 4; i++) { - fontmaps[i].etype = -1; - } - - TTF_Init(); + if (TTF_Init() == -1) + SYSERROR("Failed to intialize SDL_ttf: %s\n", TTF_GetError()); this = f; + NOTICE("FontDevice SDL_ttf\n"); + return f; } diff --git a/src/sdl_draw.c b/src/sdl_draw.c index 6ae8a78..f6c002e 100644 --- a/src/sdl_draw.c +++ b/src/sdl_draw.c @@ -362,7 +362,7 @@ static SDL_Surface *com2alphasurface(agsurface_t *src, int cl) { return s; } -static int nearest_color(int r, int g, int b) { +int sdl_nearest_color(int r, int g, int b) { int i, col, mind = INT_MAX; for (i = 0; i < 256; i++) { int dr = r - sdl_col[i].r; @@ -397,7 +397,7 @@ static void sdl_drawAntiAlias_8bpp(int dstx, int dsty, agsurface_t *src, unsigne *dp = cache[alpha << 8 | *dp]; } else { cache[*dp] |= 1 << alpha; - int c = nearest_color( + int c = sdl_nearest_color( (sdl_col[col].r * alpha + sdl_col[*dp].r * (7 - alpha)) / 7, (sdl_col[col].g * alpha + sdl_col[*dp].g * (7 - alpha)) / 7, (sdl_col[col].b * alpha + sdl_col[*dp].b * (7 - alpha)) / 7); diff --git a/src/sdl_private.h b/src/sdl_private.h index adf34cb..a8f6123 100644 --- a/src/sdl_private.h +++ b/src/sdl_private.h @@ -62,6 +62,7 @@ struct sdl_private_data { extern void sdl_cursor_init(void); extern void sdl_shadow_init(void); +extern int sdl_nearest_color(int r, int g, int b); #define SDL_AllocSurface(flags,w,h,d,r,g,b,a) SDL_CreateRGBSurface(0,w,h,d,r,g,b,a) diff --git a/src/xsystem35.c b/src/xsystem35.c index 952060d..d21b893 100644 --- a/src/xsystem35.c +++ b/src/xsystem35.c @@ -99,12 +99,16 @@ static char *fontname_tt[FONTTYPEMAX]; static boolean isjix0213_tt[FONTTYPEMAX]; static char fontface[FONTTYPEMAX]; -#ifdef ENABLE_SDL -static fontdev_t fontdev = FONT_FT2; +#ifdef ENABLE_SDLTTF +#define DEFAULT_FONT_DEVICE FONT_SDLTTF +#elif defined(ENABLE_SDL) +#define DEFAULT_FONT_DEVICE FONT_FT2 #else -static fontdev_t fontdev = FONT_X11; +#define DEFAULT_FONT_DEVICE FONT_X11 #endif +static fontdev_t fontdev = DEFAULT_FONT_DEVICE; + /* antialias on from command line */ static boolean font_antialias; static boolean font_noantialias; @@ -235,26 +239,22 @@ void sys_exit(int code) { } static int check_fontdev(char *devname) { +#ifdef ENABLE_SDLTTF + if (0 == strcmp(devname, "sdl")) { + return FONT_SDLTTF; + } +#endif #ifdef ENABLE_FT2 if (0 == strcmp(devname, "ft2")) { return FONT_FT2; } - if (0 == strcmp(devname, "ttf")) { - return FONT_FT2; - } #endif - #ifdef ENABLE_X11FONT if (0 == strcmp(devname, "x11")) { return FONT_X11; } #endif - -#ifdef ENABLE_SDL - return FONT_FT2; -#else - return FONT_X11; -#endif + return DEFAULT_FONT_DEVICE; } static void storeDataName(int type, int no, char *src) {