From 37b030b596dd53353e0aeb13e9382b46e24c3a40 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 30 Apr 2017 11:24:14 +0900 Subject: [PATCH] Implement text antialias --- src/sdlmain.cpp | 10 ++++-- src/sys/ags.h | 6 ++++ src/sys/ags_text.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/sdlmain.cpp b/src/sdlmain.cpp index f8b117a..d3ee81e 100644 --- a/src/sdlmain.cpp +++ b/src/sdlmain.cpp @@ -1,6 +1,10 @@ #include "common.h" #include "sys/nact.h" +extern "C" { + void ags_setAntialiasedStringMode(int on); +} + _TCHAR g_root[_MAX_PATH]; SDL_Window* g_window; @@ -20,8 +24,10 @@ int main(int argc, char *argv[]) g_window = SDL_CreateWindow(buf, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 400, 0); - // MCI åˆ�期化 - //initialize_mci(); + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-antialias") == 0) + ags_setAntialiasedStringMode(1); + } // system3 åˆ�期化 NACT* nact = new NACT(); diff --git a/src/sys/ags.h b/src/sys/ags.h index dc2d439..6a2f854 100644 --- a/src/sys/ags.h +++ b/src/sys/ags.h @@ -74,6 +74,7 @@ private: #endif void draw_char(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); + void draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color, uint8 cache[]); void draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color); uint16 convert_zenkaku(uint16 code); uint16 convert_hankaku(uint16 code); @@ -83,6 +84,11 @@ private: void draw_screen(int sx, int sy, int width, int heignt); void invalidate_screen(int sx, int sy, int width, int height); + uint8 palR(uint8 col) { return screen_palette[col] >> 16 & 0xff; } + uint8 palG(uint8 col) { return screen_palette[col] >> 8 & 0xff; } + uint8 palB(uint8 col) { return screen_palette[col] & 0xff; } + int nearest_color(int r, int g, int b); + uint32* vram[3][480]; // ‰¼‘zVRAM‚ւ̃|ƒCƒ“ƒ^ uint32 program_palette[256]; diff --git a/src/sys/ags_text.cpp b/src/sys/ags_text.cpp index a6a92e3..1761ca6 100644 --- a/src/sys/ags_text.cpp +++ b/src/sys/ags_text.cpp @@ -7,6 +7,8 @@ #include "ags.h" #include "s2utbl.h" +static bool antialias = false; + inline uint16 sjis_to_unicode(uint16 code) { if (code >= 0xa0 && code <= 0xdf) @@ -22,6 +24,10 @@ void AGS::draw_text(char string[]) int screen, *dest_x, dest_y, font_size; uint8 font_color; + uint8 antialias_cache[256*7]; + if (antialias) + memset(antialias_cache, 0, 256); + if (draw_menu) { screen = 2; dest_x = &menu_dest_x; @@ -54,7 +60,10 @@ void AGS::draw_text(char string[]) if((0xeb9f <= code && code <= 0xebfc) || (0xec40 <= code && code <= 0xec9e)) { draw_gaiji(screen, *dest_x, dest_y, code, font_size, font_color); } else { - draw_char(screen, *dest_x, dest_y, code, font_size, font_color); + if (antialias) + draw_char_antialias(screen, *dest_x, dest_y, code, font_size, font_color, antialias_cache); + else + draw_char(screen, *dest_x, dest_y, code, font_size, font_color); } // ‰æ–Ê�X�V if(screen == 0) { @@ -81,7 +90,6 @@ void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, int size, uin SDL_Surface* fs = TTF_RenderGlyph_Solid(font, sjis_to_unicode(code), white); // ƒpƒ^�[ƒ“�o—Í - // TODO: Blit? for(int y = 0; y < size && y < fs->w && dest_y + y < 480; y++) { uint8 *pattern = (uint8*)surface_line(fs, y); // FIXME: do not assume 8bpp for(int x = 0; x < size && x < fs->h && dest_x + x < 640; x++) { @@ -94,6 +102,64 @@ void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, int size, uin SDL_FreeSurface(fs); } +int AGS::nearest_color(int r, int g, int b) { + int i, col, mind = INT_MAX; + for (i = 0; i < 256; i++) { + int dr = r - palR(i); + int dg = g - palG(i); + int db = b - palB(i); + int d = dr*dr*30 + dg*dg*59 + db*db*11; + if (d < mind) { + mind = d; + col = i; + } + } + return col; +} + +void AGS::draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color, uint8 cache[]) +{ + // ƒpƒ^�[ƒ“Žæ“¾ + TTF_Font* font = NULL; + switch (size) { + case 16: font = hFont16; break; + case 24: font = hFont24; break; + case 32: font = hFont32; break; + case 48: font = hFont48; break; + case 64: font = hFont64; break; + } + + SDL_Color black = {0, 0, 0}; + SDL_Color white = {0xff, 0xff, 0xff}; + SDL_Surface* fs = TTF_RenderGlyph_Shaded(font, sjis_to_unicode(code), white, black); + + // ƒpƒ^�[ƒ“�o—Í + for(int y = 0; y < size && y < fs->w && dest_y + y < 480; y++) { + uint8 *pattern = (uint8*)surface_line(fs, y); + uint32 *dp = &vram[dest][dest_y + y][dest_x]; + for(int x = 0; x < size && x < fs->h && dest_x + x < 640; x++, dp++) { + uint8 bg = *dp; + int alpha = pattern[x] >> 5; + if (alpha == 0) { + // Transparent, do nothing + } else if (alpha == 7) { + *dp = color; + } else if (cache[bg] & 1 << alpha) { + *dp = cache[alpha << 8 | bg]; + } else { + cache[bg] |= 1 << alpha; + int c = nearest_color((palR(color) * alpha + palR(bg) * (7 - alpha)) / 7, + (palG(color) * alpha + palG(bg) * (7 - alpha)) / 7, + (palB(color) * alpha + palB(bg) * (7 - alpha)) / 7); + cache[alpha << 8 | bg] = c; + *dp = c; + } + } + } + + SDL_FreeSurface(fs); +} + void AGS::draw_gaiji(int dest, int dest_x, int dest_y, uint16 code, int size, uint8 color) { int index = (0xeb9f <= code && code <= 0xebfc) ? code - 0xeb9f : (0xec40 <= code && code <= 0xec9e) ? code - 0xec40 + 94 : 0; @@ -462,3 +528,10 @@ uint16 AGS::convert_hankaku(uint16 code) return code; } +extern "C" { + +void ags_setAntialiasedStringMode(int on) { + antialias = on != 0; +} + +}