Simplify font code

This commit is contained in:
kichikuou
2020-10-04 09:14:16 +09:00
parent 79c9bfc85a
commit f1b4c2550b
11 changed files with 208 additions and 383 deletions
+2 -6
View File
@@ -36,11 +36,7 @@ target_sources(xsystem35 PRIVATE
# Graphics
target_sources(xsystem35 PRIVATE
sdl_video.c sdl_draw.c sdl_event.c sdl_image.c sdl_cursor.c image.c)
# Font
target_sources(xsystem35 PRIVATE font_sdlttf.c)
sdl_video.c sdl_draw.c sdl_event.c sdl_image.c sdl_cursor.c image.c font.c)
# CG
target_sources(xsystem35 PRIVATE
@@ -67,7 +63,7 @@ target_sources(xsystem35 PRIVATE
# Graphics
target_sources(xsystem35 PRIVATE
ags.c font.c flood.c cg.c ecopy.c antialiase.c alpha_plane.c cursor.c)
ags.c flood.c cg.c ecopy.c antialiase.c alpha_plane.c cursor.c)
# Network
target_sources(xsystem35 PRIVATE
+5 -7
View File
@@ -138,10 +138,8 @@ void ags_init() {
nact->sys_view_area.height = SYS35_DEFAULT_HEIGHT;
sdl_Initilize();
font_init();
sdl_setFontDevice(nact->ags.font);
initPal(&pal_256);
cg_init();
}
@@ -399,7 +397,7 @@ int ags_drawString(int x, int y, const char *src, int col) {
agsurface_t *ags_drawStringToSurface(const char *str) {
char *utf8 = toUTF8(str);
agsurface_t *sf = nact->ags.font->get_glyph(utf8);
agsurface_t *sf = font_get_glyph(utf8);
free(utf8);
return sf;
}
@@ -749,7 +747,7 @@ void ags_whiteOut(int rate, boolean flag) {
}
void ags_setFont(int type, int size) {
nact->ags.font->sel_font(type, size);
font_select(type, size);
}
void ags_setCursorType(int type) {
@@ -803,12 +801,12 @@ void ags_setCursorLocation(int x, int y, boolean is_dibgeo) {
void ags_setAntialiasedStringMode(boolean on) {
if (!nact->noantialias) {
nact->ags.font->antialiase_on = on;
font_set_antialias(on);
}
}
boolean ags_getAntialiasedStringMode() {
return nact->ags.font->antialiase_on;
return font_get_antialias();
}
void ags_fullscreen(boolean on) {
-4
View File
@@ -30,8 +30,6 @@
#include "cg.h"
#include "graphics.h"
struct _FONT;
/* マウスカーソルの種類 */
#define CURSOR_ARROW 1
#define CURSOR_CROSS 2
@@ -129,8 +127,6 @@ struct _ags {
boolean fullscree_is_on; /* if full-screen mode then true */
struct _FONT *font; /* font device */
agsurface_t *dib; /* main surface */
void (*eventcb)(agsevent_t *e); /* deliver event */
};
+191 -9
View File
@@ -1,6 +1,4 @@
/*
* font.c font device selecter
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
@@ -19,21 +17,205 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: font.c,v 1.1 2002/09/18 13:16:22 chikama Exp $ */
#include "config.h"
#include <limits.h>
#include <math.h>
#include <SDL.h>
#include <SDL_ttf.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "config.h"
#include "portab.h"
#include "nact.h"
#include "ags.h"
#include "system.h"
#include "font.h"
#include "sdl_private.h"
void font_init() {
nact->ags.font = font_sdlttf_new();
typedef struct {
int size;
int type;
TTF_Font *id;
} FontTable;
#define FONTTABLEMAX 256
static FontTable fonttbl[FONTTABLEMAX];
static int fontcnt = 0;
static FontTable *fontset;
static struct {
boolean antialiase_on;
const char *name[FONTTYPEMAX];
int face[FONTTYPEMAX];
} this;
static void font_insert(int size, int type, TTF_Font *font) {
fonttbl[fontcnt].size = size;
fonttbl[fontcnt].type = type;
fonttbl[fontcnt].id = font;
if (fontcnt >= (FONTTABLEMAX -1)) {
WARNING("Font table is full.\n");
} else {
fontcnt++;
}
}
static FontTable *font_lookup(int size, int type) {
int i;
for (i = 0; i < fontcnt; i++) {
if (fonttbl[i].size == size && fonttbl[i].type == type) {
return &fonttbl[i];
}
}
return NULL;
}
void font_select(int type, int size) {
FontTable *tbl;
if (NULL == (tbl = font_lookup(size, type))) {
TTF_Font *fs;
fs = TTF_OpenFontIndex(this.name[type], size, this.face[type]);
if (fs == NULL) {
WARNING("%s is not found:\n", this.name[type]);
return;
}
font_insert(size, type, fs);
fontset = &fonttbl[fontcnt - 1];
} else {
fontset = tbl;
}
}
agsurface_t *font_get_glyph(const char *str_utf8) {
static SDL_Surface *fs;
static agsurface_t result;
if (!fontset)
return NULL;
if (fs) {
SDL_FreeSurface(fs);
fs = NULL;
}
SDL_Color color = {255, 255, 255, 0};
if (this.antialiase_on) {
fs = TTF_RenderUTF8_Shaded(fontset->id, str_utf8, color, color);
} else {
fs = TTF_RenderUTF8_Solid(fontset->id, str_utf8, color);
}
if (!fs) {
WARNING("Text rendering failed: %s\n", TTF_GetError());
return NULL;
}
result.depth = fs->format->BitsPerPixel;
result.bytes_per_pixel = fs->format->BytesPerPixel;
result.bytes_per_line = fs->pitch;
result.pixel = fs->pixels;
result.width = fs->w;
result.height = fs->h;
return &result;
}
// 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);
}
int font_draw_glyph(int x, int y, const char *str_utf8, int cl) {
SDL_Surface *fs;
SDL_Rect r_src, r_dst;
int w, h, maxy;
if (!*str_utf8)
return 0;
if (!fontset)
return 0;
if (this.antialiase_on) {
fs = TTF_RenderUTF8_Blended(fontset->id, str_utf8, sdl_col[cl]);
} else {
fs = TTF_RenderUTF8_Solid(fontset->id, str_utf8, sdl_col[cl]);
}
if (!fs) {
WARNING("Text rendering failed: %s\n", TTF_GetError());
return 0;
}
TTF_SizeUTF8(fontset->id, str_utf8, &w, &h);
y = max(0, y - (TTF_FontAscent(fontset->id) - fontset->size * 0.9));
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);
return w;
}
void font_init(void) {
this.antialiase_on = FALSE;
if (TTF_Init() == -1)
SYSERROR("Failed to intialize SDL_ttf: %s\n", TTF_GetError());
}
void font_set_name_and_index(int type, const char *name, int index) {
this.name[type] = name;
this.face[type] = index;
}
void font_set_antialias(boolean enable) {
this.antialiase_on = enable;
}
boolean font_get_antialias(void) {
return this.antialiase_on;
}
#ifdef __EMSCRIPTEN__
+7 -21
View File
@@ -32,30 +32,16 @@
struct agsurface;
struct _FONT {
boolean antialiase_on;
char *name[FONTTYPEMAX];
char face[FONTTYPEMAX];
void (*sel_font)(int type, int size);
struct agsurface *(*get_glyph)(const char *str_utf8);
int (*draw_glyph)(int x, int y, const char *str_utf8, int col);
boolean (*self_drawable)();
};
typedef struct _FONT FONT;
extern void font_init(void);
extern FONT *font_sdlttf_new();
extern void font_set_name_and_index(int type, const char *name, int index);
extern void font_set_antialias(boolean enable);
extern boolean font_get_antialias(void);
extern void font_select(int type, int size);
extern struct agsurface *font_get_glyph(const char *str_utf8);
extern int font_draw_glyph(int x, int y, const char *str_utf8, int col);
#ifdef __EMSCRIPTEN__
int load_mincho_font(void);
extern int load_mincho_font(void);
#endif
#endif /* __FONT_H__ */
-197
View File
@@ -1,197 +0,0 @@
#include "config.h"
#include <limits.h>
#include <math.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include "portab.h"
#include "system.h"
#include "font.h"
#include "sdl_private.h"
typedef struct {
int size;
int type;
TTF_Font *id;
} FontTable;
#define FONTTABLEMAX 256
static FontTable fonttbl[FONTTABLEMAX];
static int fontcnt = 0;
static FontTable *fontset;
static FONT *this;
static void font_insert(int size, int type, TTF_Font *font) {
fonttbl[fontcnt].size = size;
fonttbl[fontcnt].type = type;
fonttbl[fontcnt].id = font;
if (fontcnt >= (FONTTABLEMAX -1)) {
WARNING("Font table is full.\n");
} else {
fontcnt++;
}
}
static FontTable *font_lookup(int size, int type) {
int i;
for (i = 0; i < fontcnt; i++) {
if (fonttbl[i].size == size && fonttbl[i].type == type) {
return &fonttbl[i];
}
}
return NULL;
}
static void font_sdlttf_sel_font(int type, int size) {
FontTable *tbl;
if (NULL == (tbl = font_lookup(size, type))) {
TTF_Font *fs;
fs = TTF_OpenFontIndex(this->name[type], size, this->face[type]);
if (fs == NULL) {
WARNING("%s is not found:\n", this->name[type]);
return;
}
font_insert(size, type, fs);
fontset = &fonttbl[fontcnt - 1];
} else {
fontset = tbl;
}
}
static agsurface_t *font_sdlttf_get_glyph(const char *str_utf8) {
static SDL_Surface *fs;
static agsurface_t result;
if (!fontset)
return NULL;
if (fs) {
SDL_FreeSurface(fs);
fs = NULL;
}
SDL_Color color = {255, 255, 255, 0};
if (this->antialiase_on) {
fs = TTF_RenderUTF8_Shaded(fontset->id, str_utf8, color, color);
} else {
fs = TTF_RenderUTF8_Solid(fontset->id, str_utf8, color);
}
if (!fs) {
WARNING("Text rendering failed: %s\n", TTF_GetError());
return NULL;
}
result.depth = fs->format->BitsPerPixel;
result.bytes_per_pixel = fs->format->BytesPerPixel;
result.bytes_per_line = fs->pitch;
result.pixel = fs->pixels;
result.width = fs->w;
result.height = fs->h;
return &result;
}
// 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, const char *str_utf8, int cl) {
SDL_Surface *fs;
SDL_Rect r_src, r_dst;
int w, h, maxy;
if (!*str_utf8)
return 0;
if (!fontset)
return 0;
if (this->antialiase_on) {
fs = TTF_RenderUTF8_Blended(fontset->id, str_utf8, sdl_col[cl]);
} else {
fs = TTF_RenderUTF8_Solid(fontset->id, str_utf8, sdl_col[cl]);
}
if (!fs) {
WARNING("Text rendering failed: %s\n", TTF_GetError());
return 0;
}
TTF_SizeUTF8(fontset->id, str_utf8, &w, &h);
y = max(0, y - (TTF_FontAscent(fontset->id) - fontset->size * 0.9));
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);
return w;
}
static boolean drawable() {
return TRUE;
}
FONT *font_sdlttf_new() {
FONT *f = malloc(sizeof(FONT));
f->sel_font = font_sdlttf_sel_font;
f->get_glyph = font_sdlttf_get_glyph;
f->draw_glyph = font_sdlttf_draw_glyph;
f->self_drawable = drawable;
f->antialiase_on = FALSE;
if (TTF_Init() == -1)
SYSERROR("Failed to intialize SDL_ttf: %s\n", TTF_GetError());
this = f;
NOTICE("FontDevice SDL_ttf\n");
return f;
}
-3
View File
@@ -79,9 +79,6 @@ extern void* sdl_saveRegion(int x, int y, int w, int h);
extern void sdl_delRegion(void *src);
extern void sdl_maskupdate(int sx, int sy, int w, int h, int dx, int dy, int func, int step);
/* フォント関連 */
extern void sdl_setFontDevice(struct _FONT *f);
/* fader */
extern void sdl_fadeIn(int step);
extern void sdl_fadeOut(int step);
+1 -122
View File
@@ -309,59 +309,6 @@ static agsurface_t* surface2com(SDL_Surface *src) {
return dst;
}
static SDL_Surface *com2surface(agsurface_t *src) {
SDL_Surface *s;
int y;
BYTE *sp, *dp;
s = SDL_AllocSurface(SDL_SWSURFACE, src->width, src->height, src->depth, 0, 0, 0, 0);
SDL_LockSurface(s);
sp = s->pixels;
dp = src->pixel;
for (y = 0; y < src->height; y++) {
memcpy(sp, dp, src->width);
sp += s->pitch;
dp += src->bytes_per_line;
}
SDL_UnlockSurface(s);
return s;
}
static SDL_Surface *com2alphasurface(agsurface_t *src, int cl) {
SDL_Surface *s;
int x,y;
BYTE *sp, *dp;
SDL_Rect r_src;
s = SDL_CreateRGBSurfaceWithFormat(0, src->width, src->height, 32, SDL_PIXELFORMAT_ARGB8888);
setRect(r_src, 0, 0, src->width, src->height);
SDL_FillRect(s, &r_src, RGB_PIX24(sdl_col[cl].r, sdl_col[cl].g, sdl_col[cl].b));
SDL_LockSurface(s);
for (y = 0; y < src->height; y++) {
sp = src->pixel + y * src->bytes_per_line;
dp = s->pixels + y * s->pitch;
#ifndef WORDS_BIGENDIAN
dp += s->format->BytesPerPixel -1;
#endif
for (x = 0; x < src->width; x++) {
*dp = *sp;
sp++;
dp += s->format->BytesPerPixel;
}
}
SDL_UnlockSurface(s);
return s;
}
int sdl_nearest_color(int r, int g, int b) {
int i, col, mind = INT_MAX;
for (i = 0; i < 256; i++) {
@@ -377,77 +324,9 @@ int sdl_nearest_color(int r, int g, int b) {
return col;
}
static void sdl_drawAntiAlias_8bpp(int dstx, int dsty, agsurface_t *src, unsigned long col) {
int x, y;
SDL_LockSurface(sdl_dib);
Uint8 cache[256*7];
memset(cache, 0, 256);
for (y = 0; y < src->height; y++) {
BYTE* sp = src->pixel + y * src->bytes_per_line;
BYTE* dp = sdl_dib->pixels + (dsty + y) * sdl_dib->pitch + dstx;
for (x = 0; x < src->width; x++) {
int alpha = *sp >> 5;
if (alpha == 0) {
// Transparent, do nothing
} else if (alpha == 7) {
*dp = col;
} else if (cache[*dp] & 1 << alpha) {
*dp = cache[alpha << 8 | *dp];
} else {
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++;
dp++;
}
}
SDL_UnlockSurface(sdl_dib);
}
int sdl_drawString(int x, int y, const char *str_utf8, unsigned long col) {
int w;
sdl_pal_check();
if (sdl_font->self_drawable()) {
w = sdl_font->draw_glyph(x, y, str_utf8, col);
} else {
agsurface_t *glyph = sdl_font->get_glyph(str_utf8);
SDL_Rect r_src, r_dst;
if (glyph == NULL) return 0;
setRect(r_src, 0, 0, glyph->width, glyph->height);
setRect(r_dst, x, y, glyph->width, glyph->height);
if (!sdl_font->antialiase_on) {
int i;
SDL_Surface *src = com2surface(glyph);
for (i = 1; i < 256; i++) {
memcpy(src->format->palette->colors + i, &sdl_col[col],
sizeof(SDL_Color));
}
SDL_SetColorKey(src, SDL_TRUE, 0);
SDL_BlitSurface(src, &r_src, sdl_dib, &r_dst);
SDL_FreeSurface(src);
} else if (sdl_dib->format->BitsPerPixel == 8) {
sdl_drawAntiAlias_8bpp(x, y, glyph, col);
} else {
SDL_Surface *src = com2alphasurface(glyph, col);
SDL_BlitSurface(src, &r_src, sdl_dib, &r_dst);
SDL_FreeSurface(src);
}
w = glyph->width;
}
return w;
return font_draw_glyph(x, y, str_utf8, col);
}
void sdl_Mosaic(int sx, int sy, int w, int h, int dx, int dy, int slice) {
-5
View File
@@ -30,8 +30,6 @@
#include "portab.h"
#include "ags.h"
struct _FONT;
struct sdl_private_data {
SDL_Window *window;
SDL_Renderer *renderer;
@@ -48,8 +46,6 @@ struct sdl_private_data {
SDL_Rect view;
struct _FONT *font;
boolean dirty;
boolean ms_active; /* mouse is active */
@@ -78,7 +74,6 @@ extern struct sdl_private_data *sdl_videodev;
#define sdl_col (sdl_videodev->col)
#define sdl_white (sdl_videodev->white)
#define sdl_dibinfo (sdl_videodev->cimg)
#define sdl_font (sdl_videodev->font)
#define sdl_view (sdl_videodev->view)
#define view_x (sdl_videodev->view.x)
#define view_y (sdl_videodev->view.y)
-5
View File
@@ -34,7 +34,6 @@
#include "sdl_core.h"
#include "sdl_private.h"
#include "xsystem35.h"
#include "font.h"
#include "joystick.h"
#include "image.h"
@@ -173,10 +172,6 @@ static void makeDIB(int width, int height, int depth) {
image_setdepth(sdl_dibinfo->depth);
}
void sdl_setFontDevice(struct _FONT *f) {
sdl_font = f;
}
/* offscreen の設定 */
void sdl_setWorldSize(int width, int height, int depth) {
makeDIB(width, height, depth);
+2 -4
View File
@@ -217,10 +217,8 @@ static void sys35_init() {
ags_init();
for (i = 0; i < FONTTYPEMAX; i++) {
nact->ags.font->name[i] = fontname_tt[i];
nact->ags.font->face[i] = fontface[i];
}
for (i = 0; i < FONTTYPEMAX; i++)
font_set_name_and_index(i, fontname_tt[i], fontface[i]);
ags_fullscreen(fs_on);
nact->noantialias = font_noantialias;