#include "SDL_kanji.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUF 256
static void InitFont(Kanji_Font* font) {
int i;
for (i = 0; i < 96*96 + 256; i++) {
font->moji[i] = 0;
}
}
Kanji_Font* Kanji_OpenFont(const char* file, int size) {
Kanji_Font* font;
font = (Kanji_Font*)malloc(sizeof(Kanji_Font));
font->k_size = size;
font->a_size = size / 2;
font->sys = KANJI_JIS;
InitFont(font);
if (0 == Kanji_AddFont(font, file)) {
return font;
}
else {
free(font);
return 0;
}
}
static void ParseChar(Kanji_Font* font, int index, FILE* fp, int shift) {
char buf[BUF];
int y;
/* 既にロードされている文字は読み込まない */
if (font->moji[index] != 0) return;
font->moji[index] = (Uint32*)malloc(sizeof(Uint32)*font->k_size);
for (y = 0; y < font->k_size; y++) {
fgets(buf, BUF, fp);
font->moji[index][y] = (strtol(buf, 0, 16) >> shift);
}
}
static int ParseFont(Kanji_Font* font, FILE* fp) {
char buf[BUF], *p;
int index;
int k_rshift, a_rshift;
int s;
for (s = 8; s < font->k_size; s += 8) {}
k_rshift = s - font->k_size;
for (s = 8; s < font->a_size; s += 8) {}
a_rshift = s - font->a_size;
while (1) {
if (fgets(buf, BUF, fp) == NULL) {
break;
}
if (strstr(buf, "ENCODING") != NULL) {
p = strchr(buf, ' ');
index = strtol(p, 0, 10);
while (strstr(buf, "BITMAP") == NULL) {
fgets(buf, BUF, fp);
}
if (index > 255) {
index = (((index & 0xff00) >> 8) - 0x20) * 96
+ (index & 0xff) - 0x20 + 0xff;
ParseChar(font, index, fp, k_rshift);
}
else {
ParseChar(font, index, fp, a_rshift);
}
}
}
return 0;
}
int Kanji_AddFont(Kanji_Font* font, const char* file) {
FILE* fp;
fp = fopen(file, "r");
if(fp==NULL){
fprintf(stderr, "cant open [%s]\n", file);
return -1;
}
if (0 != ParseFont(font, fp)) return -1;
fclose(fp);
return 0;
}
int Kanji_FontHeight(Kanji_Font* font) {
return font->k_size;
}
int Kanji_FontWidth(Kanji_Font* font, const char* text) {
if (text == 0) return font->a_size;
else return strlen(text) * font->a_size;
}
static void KanjiPutpixel(SDL_Surface *s,int x,int y,Uint32 pixel){
Uint8 *p,bpp;
if(SDL_MUSTLOCK(s)){
if(SDL_LockSurface(s)<0) return;
}
bpp=s->format->BytesPerPixel;
p=(Uint8*)(s->pixels)+y*s->pitch+x*bpp;
switch(bpp){
case 1:
*((Uint8 *)p)=(Uint8)pixel;
break;
case 2:
*((Uint16 *)p)=(Uint16)pixel;
break;
case 4:
*((Uint32 *)p)=pixel;
break;
}
if(SDL_MUSTLOCK(s)){
SDL_UnlockSurface(s);
}
}
static void euc2jis(unsigned char *c1, unsigned char *c2)
{
*c1 &= 0x7f;
*c2 &= 0x7f;
}
static void sjis2jis(unsigned char *c1, unsigned char *c2)
{
if( *c2 < 0x9f )
{
if( *c1 < 0xa0 )
{
*c1 -= 0x81;
*c1 *= 2;
*c1 += 0x21;
}
else
{
*c1 -= 0xe0;
*c1 *= 2;
*c1 += 0x5f;
}
if( *c2 > 0x7f )
-- *c2;
*c2 -= 0x1f;
}
else
{
if( *c1 < 0xa0 )
{
*c1 -= 0x81;
*c1 *= 2;
*c1 += 0x22;
}
else
{
*c1 -= 0xe0;
*c1 *= 2;
*c1 += 0x60;
}
*c2 -= 0x7e;
}
}
static void ConvertCodingSystem(Kanji_Font* font,
unsigned char *c1, unsigned char *c2) {
if (font->sys == KANJI_SJIS) {
sjis2jis(c1, c2);
}
else if (font->sys == KANJI_EUC) {
euc2jis(c1, c2);
}
}
int Kanji_PutText(Kanji_Font* font, int dx, int dy,
SDL_Surface* dst, const char* txt, SDL_Color fg)
{
Uint32 fgcol;
int index;
int x, y, cx = dx, cy = dy;
unsigned char high, low;
int minx, miny, maxx, maxy;
int nowKanji = 0;
const unsigned char* text = (const unsigned char*)txt;
fgcol = SDL_MapRGB(dst->format, fg.r, fg.g, fg.b);
while (*text != 0) {
if (font->sys == KANJI_JIS && *text == 0x1b) {
if (*(text+1) == 0x24 && *(text+2) == 0x42) {
nowKanji = 1;
}
else if (*(text+1) == 0x28 && *(text+2) == 0x42) {
nowKanji = 0;
}
text += 3;
continue;
}
if (font->sys != KANJI_JIS) nowKanji = !isprint(*text);
if (!nowKanji) {
index = *text;
text++;
if (font->moji[index] == 0) {
cx += font->a_size;
continue;
}
minx = (cx >= 0) ? 0 : -cx;
miny = (cy >= 0) ? 0 : -cy;
maxx = (cx+font->a_size <= dst->w) ? font->a_size : dst->w-cx;
maxy = (cy+font->k_size <= dst->h) ? font->k_size : dst->h-cy;
for (y = miny; y < maxy; y++) {
for (x = minx; x < maxx; x++) {
if (font->moji[index][y] & (1 << (font->a_size-x-1))) {
KanjiPutpixel(dst, cx+x, cy+y, fgcol);
}
}
}
cx += font->a_size;
}
else {
high = *text;
low = *(text+1);
ConvertCodingSystem(font, &high, &low);
index = (high - 0x20) * 96 + low - 0x20 + 0xff;
text += 2;
if (font->moji[index] == 0) {
cx += font->k_size;
continue;
}
minx = (cx >= 0) ? 0 : -cx;
miny = (cy >= 0) ? 0 : -cy;
maxx = (cx+font->k_size <= dst->w) ? font->k_size : dst->w-cx;
maxy = (cy+font->k_size <= dst->h) ? font->k_size : dst->h-cy;
for (y = miny; y < maxy; y++) {
for (x = minx; x < maxx; x++) {
if (font->moji[index][y] & (1 << (font->k_size-x-1))) {
KanjiPutpixel(dst, cx+x, cy+y, fgcol);
}
}
}
cx += font->k_size;
}
}
return 0;
}
int Kanji_PutTextTate(Kanji_Font* font, int dx, int dy,
SDL_Surface* dst, const char* txt, SDL_Color fg)
{
Uint32 fgcol;
int index;
int x, y, cx = dx, cy = dy;
unsigned char high, low;
int minx, miny, maxx, maxy;
int nowKanji = 0;
const unsigned char* text = (const unsigned char*)txt;
fgcol = SDL_MapRGB(dst->format, fg.r, fg.g, fg.b);
while (*text != 0) {
if (font->sys == KANJI_JIS && *text == 0x1b) {
if (*(text+1) == 0x24 && *(text+2) == 0x42) {
nowKanji = 1;
}
else if (*(text+1) == 0x28 && *(text+2) == 0x42) {
nowKanji = 0;
}
text += 3;
continue;
}
if (font->sys != KANJI_JIS) nowKanji = !isprint(*text);
/* ASCII は無視 */
if (!nowKanji) {
text++;
}
else {
high = *text;
low = *(text+1);
ConvertCodingSystem(font, &high, &low);
index = (high - 0x20) * 96 + low - 0x20 + 0xff;
text += 2;
if (font->moji[index] == 0) {
cy += font->k_size;
continue;
}
if (high == 0x21 && (low >= 0x22 || low <= 0x25)) {
cx += font->k_size * 0.6;
cy -= font->k_size * 0.6;
}
minx = (cx >= 0) ? 0 : -cx;
miny = (cy >= 0) ? 0 : -cy;
maxx = (cx+font->k_size <= dst->w) ? font->k_size : dst->w-cx;
maxy = (cy+font->k_size <= dst->h) ? font->k_size : dst->h-cy;
for (y = miny; y < maxy; y++) {
for (x = minx; x < maxx; x++) {
if (font->moji[index][y] & (1 << (font->k_size-x-1))) {
KanjiPutpixel(dst, cx+x, cy+y, fgcol);
}
}
}
if (high == 0x21 && (low >= 0x22 || low <= 0x25)) {
cx -= font->k_size * 0.6;
cy += font->k_size * 1.6;
}
else {
cy += font->k_size;
}
}
}
return 0;
}
SDL_Surface* Kanji_CreateSurface(Kanji_Font* font, const char* text,
SDL_Color fg, int bpp)
{
SDL_Surface* textbuf;
int len;
Uint32 bgcol;
if (text == NULL) return NULL;
if (*text == 0 ) return NULL;
len = strlen(text);
textbuf = SDL_AllocSurface(SDL_SWSURFACE, font->a_size*len, font->k_size,
bpp, 0, 0, 0, 0);
if (textbuf == NULL) {
fprintf(stderr,"ERROR: at Kanji_RenderText\n");
return NULL;
}
bgcol = SDL_MapRGB(textbuf->format, 255-fg.r, 255-fg.g, 255-fg.b);
SDL_FillRect(textbuf, NULL, bgcol);
SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, bgcol);
Kanji_PutText(font, 0, 0, textbuf, text, fg);
return textbuf;
}
SDL_Surface* Kanji_CreateSurfaceTate(Kanji_Font* font, const char* text,
SDL_Color fg, int bpp)
{
SDL_Surface* textbuf;
int len;
Uint32 bgcol;
if (text == NULL) return NULL;
if (*text == 0 ) return NULL;
len = strlen(text);
textbuf = SDL_AllocSurface(SDL_SWSURFACE, font->k_size, font->a_size*len,
bpp, 0, 0, 0, 0);
if (textbuf == NULL) {
fprintf(stderr,"ERROR: at Kanji_RenderText\n");
return NULL;
}
bgcol = SDL_MapRGB(textbuf->format, 255-fg.r, 255-fg.g, 255-fg.b);
SDL_FillRect(textbuf, NULL, bgcol);
SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, bgcol);
Kanji_PutTextTate(font, 0, 0, textbuf, text, fg);
return textbuf;
}
void Kanji_CloseFont(Kanji_Font* font) {
int i;
for (i = 0; i < 96*96 + 256; i++) {
if (font->moji[i] != 0) {
free(font->moji[i]);
}
}
free(font);
}
void Kanji_SetCodingSystem(Kanji_Font* font, Kanji_CodingSystem sys) {
font->sys = sys;
}
syntax highlighted by Code2HTML, v. 0.9.1