diff --git a/README.md b/README.md index 9a6d9d1..17f878d 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Neko Project II 0.86 kai -Mar 2, 2020
+Mar 6, 2020
NP2kai is PC-9801 series emulator
@@ -498,6 +498,37 @@ Rhythm sound files are dumped from PC-98 machine with FM sound gen.
You can get sound files from [here](https://sites.google.com/site/ym2608rhythm/). +
+Fonts +
+ +NP2kai recommend font is using font.rom.
+ +### Windows + +You can use 'MS Gothic'. To install add your windows,
+'install files Easten Asian languages' at 'language' option.
+ +After installation, 'msgothic.ttc' file's shortcut named 'default.ttf' put in BIOS directory.
+(Already exist 'font.tmp', delete this.)
+And start NP2kai. + +### Linux + +I recommend use 'Takao Gothic'.
+Install with follow command. +``` +sudo apt install 'fonts-takao-*' +``` +and +``` +ls -n /usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf BIOSdirectory/default.ttf' +``` +After installation, '/usr/share/fonts/msgothic.ttc' file's shortcut put in BIOS directory.
+(Already exist 'font.tmp', delete this.)
+And start NP2kai. +
+
NP2 menu (different libretro menu)
@@ -992,6 +1023,8 @@ Next boot computer, you command from 4.
## Release +- Mar 6, 2020
+ - [X11] fix default.ttf
- Mar 2, 2020
- Using absolute/rerative path in .m3u and .cmd list file
- [lr] not remember last HDD mount
diff --git a/x11/Makefile.am b/x11/Makefile.am index a9243a8..2e28434 100755 --- a/x11/Makefile.am +++ b/x11/Makefile.am @@ -66,7 +66,6 @@ COMMON_SOURCES= $(real_topsrcdir)/x11/main.c \ $(real_topsrcdir)/x11/gtk2/window_softkbd.c \ $(real_topsrcdir)/x11/gtk2/gtk_drawmng.c \ $(real_topsrcdir)/x11/gtk2/gtk_screen.c \ - $(real_topsrcdir)/x11/gtk2/gtk_font.c \ $(real_topsrcdir)/x11/gtk2/gtk_keyboard.c \ $(real_topsrcdir)/x11/gtk2/gtk_menu.c \ $(real_topsrcdir)/x11/gtk2/gtk_mouse.c \ diff --git a/x11/fontmng.c b/x11/fontmng.c index d138e83..b382f92 100755 --- a/x11/fontmng.c +++ b/x11/fontmng.c @@ -1,4 +1,650 @@ -#include "compiler.h" +/** + * @file fontmng.c + * @brief Implementation of the font manager + */ -#include "np2.h" +#include "compiler.h" #include "fontmng.h" + +#include "ank12.res" + +#define USE_TTF + +#if defined(USE_TTF) /* use TTF */ + +#include + +#define FONTMNG_CACHE 64 /*!< Cache count */ + +/*! White */ +static const SDL_Color s_white = {0xff, 0xff, 0xff, 0}; + +#if defined(FONTMNG_CACHE) +typedef struct +{ + UINT16 str; /*!< String Id */ + UINT16 next; /*!< Next index */ +} FNTCTBL; +#endif + +#endif /* defined(USE_TTF) */ + +/*! Font face */ +static char s_sFontName[MAX_PATH] = "default.ttf"; + +/** + * @brief Handle + */ +struct TagFontManager +{ + int fontsize; + UINT fonttype; + +#if defined(USE_TTF) + TTF_Font *ttf_font; + int ptsize; + int fontalign; +#endif /* defined(USE_TTF) */ + +#if defined(FONTMNG_CACHE) + UINT caches; + UINT cachehead; + FNTCTBL cache[FONTMNG_CACHE]; +#endif /* defined(FONTMNG_CACHE) */ +}; +typedef struct TagFontManager *FNTMNG; /*!< Defines handle */ + +#if defined(FONTMNG_CACHE) +/** + * + */ +static BOOL fdatgetcache(FNTMNG fhdl, UINT16 c, FNTDAT *pfdat) +{ + BOOL r; + FNTCTBL *fct; + UINT pos; + UINT prev; + UINT cnt; + + r = FALSE; + fct = fhdl->cache; + cnt = fhdl->caches; + pos = fhdl->cachehead; + prev = FONTMNG_CACHE; + while (cnt--) + { + if (fct[pos].str != c) + { + prev = pos; + pos = fct[pos].next; + continue; + } + if (prev < FONTMNG_CACHE) + { + fct[prev].next = fct[pos].next; + fct[pos].next = (UINT16)fhdl->cachehead; + fhdl->cachehead = pos; + } + r = TRUE; + break; + } + if (r == FALSE) + { + if (fhdl->caches < FONTMNG_CACHE) + { + pos = fhdl->caches; + fhdl->caches++; + } + else + { + pos = prev; + } + fct[pos].str = c; + fct[pos].next = (UINT16)fhdl->cachehead; + fhdl->cachehead = pos; + } + if (pfdat) + { + *pfdat = (FNTDAT)(((UINT8 *)(fhdl + 1)) + (pos * fhdl->fontalign)); + } + return r; +} +#endif /* defined(FONTMNG_CACHE) */ + +/** + * Initialize + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_init(void) +{ +#if defined(USE_TTF) + + if (TTF_Init() < 0) + { + fprintf(stderr, "Couldn't initialize TTF: %s\n", SDL_GetError()); + return FAILURE; + } +#ifndef WIN32 + atexit(TTF_Quit); +#endif + +#endif /* defined(USE_TTF) */ + + return SUCCESS; +} + +/** + * Sets font face + * @param[in] name name + */ +void fontmng_setdeffontname(const char *name) +{ + milstr_ncpy(s_sFontName, name, NELEMENTS(s_sFontName)); +} + +/** + * Creates instance + */ +void *fontmng_create(int size, UINT type, const char *fontface) +{ + int fontalign; + int fontwork; + int allocsize; + FNTMNG ret; + +#if defined(USE_TTF) + TTF_Font *ttf_font; + int ptsize; +#endif /* defined(USE_TTF) */ + + if (size < 0) + { + size = -size; + } + if (size < 6) + { + size = 6; + } + else if (size > 128) + { + size = 128; + } + +#if defined(USE_TTF) + + if (size < 10) + { + type |= FDAT_ALIAS; + } + else if (size < 16) + { + type &= ~FDAT_BOLD; + } + + ptsize = size; + if (type & FDAT_ALIAS) + { + ptsize *= 2; + } + ttf_font = TTF_OpenFont(s_sFontName, ptsize); + if (ttf_font == NULL) + { + fprintf(stderr, "Couldn't load %d points font from %s: %s\n", ptsize, s_sFontName, SDL_GetError()); + + if (size < ANKFONTSIZE) + { + return NULL; + } + + ptsize = size; + type &= FDAT_PROPORTIONAL; + } + +#else /* defined(USE_TTF) */ + + if (size < ANKFONTSIZE) + { + return NULL; + } + +#endif /* defined(USE_TTF) */ + + fontalign = sizeof(_FNTDAT) + (size * size); + fontalign = (fontalign + 3) & (~3); +#if defined(FONTMNG_CACHE) + fontwork = fontalign * FONTMNG_CACHE; +#else + fontwork = fontalign; +#endif + + allocsize = sizeof(*ret) + fontwork; + ret = (FNTMNG)_MALLOC(allocsize, "font mng"); + if (ret == NULL) + { +#if defined(USE_TTF) + TTF_CloseFont(ttf_font); +#endif /* defined(USE_TTF) */ + return NULL; + } + + memset(ret, 0, allocsize); + ret->fontsize = size; + ret->fonttype = type; + +#if defined(USE_TTF) + ret->ttf_font = ttf_font; + ret->ptsize = ptsize; + ret->fontalign = fontalign; +#endif /* defined(USE_TTF) */ + + return ret; +} + +/** + * Destroy + * @param[in] hdl Handle + */ +void fontmng_destroy(void *hdl) +{ + FNTMNG _this; + + _this = (FNTMNG)hdl; + if (_this) + { + +#if defined(USE_TTF) + TTF_CloseFont(_this->ttf_font); +#endif /* defined(USE_TTF) */ + + _MFREE(_this); + } +} + +/** + * Sets font header + * @param[in] _this Instance + * @param[out] fdat Data header + * @param[in] s SDL_Surface + */ +static void AnkSetFontHeader(FNTMNG _this, FNTDAT fdat, int width) +{ + if (_this->fonttype & FDAT_PROPORTIONAL) + { + fdat->width = width; + fdat->pitch = width + 1; + fdat->height = _this->fontsize; + } + else + { + fdat->width = np2max(width, _this->fontsize >> 1); + fdat->pitch = (_this->fontsize >> 1) + 1; + fdat->height = _this->fontsize; + } +} + +/** + * Gets font length + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void AnkGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + c = c - 0x20; + if ((c < 0) || (c >= 0x60)) + { + c = 0x1f; /* '?' */ + } + AnkSetFontHeader(_this, fdat, ankfont[c * ANKFONTSIZE]); +} + +/** + * Gets font face (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void AnkGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ +const UINT8 *src; + int width; + UINT8 *dst; + int x; + int y; + + c = c - 0x20; + if ((c < 0) || (c >= 0x60)) + { + c = 0x1f; /* '?' */ + } + src = ankfont + (c * ANKFONTSIZE); + width = *src++; + AnkSetFontHeader(_this, fdat, width); + dst = (UINT8 *)(fdat + 1); + memset(dst, 0, fdat->width * fdat->height); + dst += ((fdat->height - ANKFONTSIZE) / 2) * fdat->width; + dst += (fdat->width - width) / 2; + for (y = 0; y < (ANKFONTSIZE - 1); y++) + { + dst += fdat->width; + for (x = 0; x < width; x++) + { + dst[x] = (src[0] & (0x80 >> x)) ? 0xff : 0x00; + } + src++; + } +} + +#define GetLength1 TTFGetLength1 /*!< length function */ +#define GetFont1 TTFGetFont1 /*!< face function */ + +/** + * Sets font header (TTF) + * @param[in] _this Instance + * @param[out] fdat Data header + * @param[in] s SDL_Surface + */ +static void TTFSetFontHeader(FNTMNG _this, FNTDAT fdat, const SDL_Surface *s) +{ + int width; + int height; + int pitch; + + if (s) + { + width = np2min(s->w, _this->ptsize); + height = np2min(s->h, _this->ptsize); + } + else + { + width = _this->fontsize; + height = _this->fontsize; + } + + pitch = width; + if (_this->fonttype & FDAT_ALIAS) + { + width = (width + 1) >> 1; + pitch = width >> 1; + height = (height + 1) >> 1; + } + fdat->width = width; + fdat->pitch = pitch; + fdat->height = height; +} + +/** + * Get pixel + * @param[in] s SDL_Surface + * @param[in] x x + * @param[in] y y + * @return pixel + */ +static UINT8 TTFGetPixelDepth(const SDL_Surface *s, int x, int y) +{ + int nXAlign; + const UINT8 *ptr; + + if ((x >= 0) && (x < s->w) && (y >= 0) && (y < s->h)) + { + nXAlign = s->format->BytesPerPixel; + ptr = (UINT8 *)s->pixels + (y * s->pitch) + (x * nXAlign); + switch (nXAlign) + { + case 1: + return (ptr[0] != 0) ? FDAT_DEPTH : 0; + + case 3: + case 4: + return (ptr[0] * FDAT_DEPTH / 255); + } + } + return 0; +} + +/** + * Gets font length (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void TTFGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + UINT16 sString[2]; + SDL_Surface *s; + + sString[0] = c; + sString[1] = 0; + s = NULL; + if (_this->ttf_font) + { + s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); + } + if (s) + { + TTFSetFontHeader(_this, fdat, s); + SDL_FreeSurface(s); + } + else + { + AnkGetLength1(_this, fdat, c); + } +} + +/** + * Gets font face (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void TTFGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + UINT16 sString[2]; + SDL_Surface *s; + UINT8 *dst; + int x; + int y; + int depth; + + sString[0] = c; + sString[1] = 0; + s = NULL; + if (_this->ttf_font) + { + s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); + } + if (s) + { + TTFSetFontHeader(_this, fdat, s); + dst = (UINT8 *)(fdat + 1); + if (_this->fonttype & FDAT_ALIAS) + { + for (y = 0; y < fdat->height; y++) + { + for (x = 0; x < fdat->width; x++) + { + depth = TTFGetPixelDepth(s, x*2+0, y*2+0); + depth += TTFGetPixelDepth(s, x*2+1, y*2+0); + depth += TTFGetPixelDepth(s, x*2+0, y*2+1); + depth += TTFGetPixelDepth(s, x*2+1, y*2+1); + *dst++ = (UINT8)((depth + 2) / 4); + } + } + } + else + { + for (y = 0; y < fdat->height; y++) + { + for (x = 0; x < fdat->width; x++) + { + *dst++ = TTFGetPixelDepth(s, x, y); + } + } + } + SDL_FreeSurface(s); + } + else + { + AnkGetFont1(_this, fdat, c); + } +} + +/** + * Get charactor + * @param[in,out] lppString Pointer + * @return Charactor + */ +static UINT16 GetChar(const char** lppString) +{ + const char *lpString; + UINT16 c; + + lpString = *lppString; + if (lpString == NULL) + { + return 0; + } + + c = 0; + if ((lpString[0] & 0x80) == 0) + { + c = lpString[0] & 0x7f; + lpString++; + } + else if (((lpString[0] & 0xe0) == 0xc0) && ((lpString[1] & 0xc0) == 0x80)) + { + c = ((lpString[0] & 0x1f) << 6) | (lpString[1] & 0x3f); + lpString += 2; + } + else if (((lpString[0] & 0xf0) == 0xe0) && ((lpString[1] & 0xc0) == 0x80) && ((lpString[2] & 0xc0) == 0x80)) + { + c = ((lpString[0] & 0x0f) << 12) | ((lpString[1] & 0x3f) << 6) | (lpString[2] & 0x3f); + lpString += 3; + } + + *lppString = lpString; + return c; +} + +/** + * Get font size + * @param[in] hdl Handle + * @param[in] lpString String + * @param[out] pt Size + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_getsize(void *hdl, const char *lpString, POINT_T *pt) +{ + FNTMNG _this; + int nWidth; + UINT16 c; + _FNTDAT fontData; + + _this = (FNTMNG)hdl; + if ((_this == NULL) || (lpString == NULL)) + { + return FAILURE; + } + + nWidth = 0; + while (1 /* EVER */) + { + c = GetChar(&lpString); + if (c == 0) + { + break; + } + GetLength1(_this, &fontData, c); + nWidth += fontData.pitch; + } + + if (pt) + { + pt->x = nWidth; + pt->y = _this->fontsize; + } + return SUCCESS; +} + +/** + * Get draw area + * @param[in] hdl Handle + * @param[in] lpString String + * @param[out] pt An area + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_getdrawsize(void *hdl, const char *lpString, POINT_T *pt) +{ + FNTMNG _this; + int nWidth; + int nPosX; + UINT16 c; + _FNTDAT fontData; + + _this = (FNTMNG)hdl; + if (_this == NULL) + { + return FAILURE; + } + + nWidth = 0; + nPosX = 0; + while (1 /* EVER */) + { + c = GetChar(&lpString); + if (c == 0) + { + break; + } + GetLength1(_this, &fontData, c); + nWidth = nPosX + np2max(fontData.width, fontData.pitch); + nPosX += fontData.pitch; + } + if (pt) + { + pt->x = nWidth; + pt->y = _this->fontsize; + } + return SUCCESS; +} + +/** + * Get font data + * @param[in] hdl Handle + * @param[in] lpString String + * @return Data + */ +FNTDAT fontmng_get(void *hdl, const char *lpString) +{ + FNTMNG _this; + UINT16 c; + FNTDAT fontData; + + _this = (FNTMNG)hdl; + if (_this == NULL) + { + return NULL; + } + + c = GetChar(&lpString); + if (c == 0) + { + return NULL; + } + +#if defined(FONTMNG_CACHE) + if (fdatgetcache(_this, c, &fontData)) + { + return fontData; + } +#else /*! defined(FONTMNG_CACHE) */ + fontData = (FNTDAT)(_this + 1); +#endif /*! defined(FONTMNG_CACHE) */ + + GetFont1(_this, fontData, c); + return fontData; +} + diff --git a/x11/fontmng.h b/x11/fontmng.h index b08a65c..5f35f08 100755 --- a/x11/fontmng.h +++ b/x11/fontmng.h @@ -22,7 +22,6 @@ typedef struct { } _FNTDAT, *FNTDAT; BRESULT fontmng_init(void); -void fontmng_terminate(void); void fontmng_setdeffontname(const OEMCHAR *fontface); void* fontmng_create(int size, UINT type, const OEMCHAR *fontface); void fontmng_destroy(void *hdl); diff --git a/x11/gtk2/gtk_menu.c b/x11/gtk2/gtk_menu.c index 3de7320..00b111b 100755 --- a/x11/gtk2/gtk_menu.c +++ b/x11/gtk2/gtk_menu.c @@ -148,7 +148,7 @@ static GtkActionEntry menu_entries[] = { { "disk4eject", NULL, "_Eject", NULL, NULL, G_CALLBACK(cb_diskeject), }, { "disk4open", NULL, "_Open...", NULL, NULL, G_CALLBACK(cb_diskopen), }, { "exit", NULL, "E_xit", NULL, NULL, G_CALLBACK(gtk_main_quit) }, -{ "font", NULL, "_Font...", NULL, NULL, G_CALLBACK(cb_change_font), }, +//{ "font", NULL, "_Font...", NULL, NULL, G_CALLBACK(cb_change_font), }, { "newfdisk", NULL, "_Floppy disk image...", NULL, NULL, G_CALLBACK(cb_newfdisk) }, { "newhdisk", NULL, "_Hard disk image...", NULL, NULL, G_CALLBACK(cb_newhdisk) }, #if defined(SUPPORT_IDEIO) @@ -444,7 +444,7 @@ static const gchar *ui_info = " \n" " \n" " \n" -" \n" +//" \n" " \n" " \n" " \n" diff --git a/x11/main.c b/x11/main.c index 3c3c9ec..21f8a51 100755 --- a/x11/main.c +++ b/x11/main.c @@ -144,6 +144,8 @@ main(int argc, char *argv[]) int rv = 1; int ch; int i, drvmax; + char fontfile[MAX_PATH]; + FILE *fcheck; progname = argv[0]; @@ -260,6 +262,17 @@ main(int argc, char *argv[]) } if (modulefile[0] != '\0') { /* font file */ + file_cpyname(fontfile, modulefile, sizeof(fontfile)); + file_cutname(fontfile); + file_setseparator(fontfile, sizeof(fontfile)); + file_catname(fontfile, "default.ttf", sizeof(fontfile)); + fcheck = fopen(fontfile, "rb"); + if (fcheck != NULL) { + fclose(fcheck); + fontmng_setdeffontname(fontfile); + } + + /* font bmp file */ file_cpyname(np2cfg.fontfile, modulefile, sizeof(np2cfg.fontfile)); file_cutname(np2cfg.fontfile); @@ -451,8 +464,6 @@ main(int argc, char *argv[]) scrnmng_destroy(); scrnmng_failure: - fontmng_terminate(); - fontmng_failure: if (!np2oscfg.readonly && (sys_updates & (SYS_UPDATECFG|SYS_UPDATEOSCFG))) {