/* font2fontx.c code: SASANO Takayoshi ---- CC-BY, no warranty. [charset=UTF-8] ●概要 TOWNS OSのFONT2形式のフォントをFONTX2形式に変換する。 */ #include #include #include /* FONTX2 header */ #define CODETYPE_ASCII 0 #define CODETYPE_KANJI 1 /* common */ typedef struct { unsigned char identifier[6]; unsigned char fontname[8]; unsigned char xsize; unsigned char ysize; unsigned char codetype; } __attribute__((packed)) FONTX2_HEADER; /* ascii */ typedef struct { FONTX2_HEADER h; unsigned char d[1]; } __attribute__((packed)) FONTX2_ASCII; /* sjis */ typedef struct { FONTX2_HEADER h; unsigned char tnum; // unsigned char d[1]; } __attribute__((packed)) FONTX2_KANJI; typedef struct { unsigned short start; unsigned short end; } __attribute__((packed)) FONTX2_CODETABLE; static FONTX2_CODETABLE CodeTable_SJIS[] = { {0x8140, 0x817e}, {0x8180, 0x81ac}, /* symbol */ {0x81b8, 0x81bf}, {0x81c8, 0x81ce}, {0x81da, 0x81e8}, {0x81f0, 0x81f7}, {0x81fc, 0x81fc}, {0x824f, 0x8258}, /* number */ {0x8260, 0x8279}, /* alphabet (large) */ {0x8281, 0x829a}, /* alphabet (small) */ {0x829f, 0x82f1}, /* hiragana */ {0x8340, 0x837e}, {0x8380, 0x8396}, /* katakana */ {0x839f, 0x83b6}, /* greek (large) */ {0x83bf, 0x83d6}, /* greek (small) */ {0x8440, 0x8460}, /* russian (large) */ {0x8470, 0x847e}, {0x8480, 0x8491}, /* russian (small) */ {0x849f, 0x84be}, /* keisen */ {0x889f, 0x88fc}, /* kanji (JIS1) */ {0x8940, 0x897e}, {0x8980, 0x89fc}, {0x8a40, 0x8a7e}, {0x8a80, 0x8afc}, {0x8b40, 0x8b7e}, {0x8b80, 0x8bfc}, {0x8c40, 0x8c7e}, {0x8c80, 0x8cfc}, {0x8d40, 0x8d7e}, {0x8d80, 0x8dfc}, {0x8e40, 0x8e7e}, {0x8e80, 0x8efc}, {0x8f40, 0x8f7e}, {0x8f80, 0x8ffc}, {0x9040, 0x907e}, {0x9080, 0x90fc}, {0x9140, 0x917e}, {0x9180, 0x91fc}, {0x9240, 0x927e}, {0x9280, 0x92fc}, {0x9340, 0x937e}, {0x9380, 0x93fc}, {0x9440, 0x947e}, {0x9480, 0x94fc}, {0x9540, 0x957e}, {0x9580, 0x95fc}, {0x9640, 0x967e}, {0x9680, 0x96fc}, {0x9740, 0x977e}, {0x9780, 0x97fc}, {0x9840, 0x9872}, {0x989f, 0x98fc}, /* kanji (JIS2) */ {0x9940, 0x997e}, {0x9980, 0x99fc}, {0x9a40, 0x9a7e}, {0x9a80, 0x9afc}, {0x9b40, 0x9b7e}, {0x9b80, 0x9bfc}, {0x9c40, 0x9c7e}, {0x9c80, 0x9cfc}, {0x9d40, 0x9d7e}, {0x9d80, 0x9dfc}, {0x9e40, 0x9e7e}, {0x9e80, 0x9efc}, {0x9f40, 0x9f7e}, {0x9f80, 0x9ffc}, {0xe040, 0xe07e}, {0xe080, 0xe0fc}, {0xe140, 0xe17e}, {0xe180, 0xe1fc}, {0xe240, 0xe27e}, {0xe280, 0xe2fc}, {0xe340, 0xe37e}, {0xe380, 0xe3fc}, {0xe440, 0xe47e}, {0xe480, 0xe4fc}, {0xe540, 0xe57e}, {0xe580, 0xe5fc}, {0xe640, 0xe67e}, {0xe680, 0xe6fc}, {0xe740, 0xe77e}, {0xe780, 0xe7fc}, {0xe840, 0xe87e}, {0xe880, 0xe8fc}, {0xe940, 0xe97e}, {0xe980, 0xe9fc}, {0xea40, 0xea7e}, {0xea80, 0xeaa4}, }; /* data buffer (in/out) */ #define BUFFERSIZE (6144 * 1024) static char InData[BUFFERSIZE]; static char FontName[] = "TOWNS"; static int X_SIZE; static int Y_SIZE; #define OFFSET_ASCII 16 #define OFFSET_KANJI (256 * ((X_SIZE + 15) / 16) * Y_SIZE + OFFSET_ASCII) #define KANJI_SIZE (((X_SIZE + 7) / 8) * Y_SIZE) /* SJIS -> JIS */ static int _mbcjmstojis(int jms) { int low, high; high = (jms >> 8) & 0xff; low = jms & 0xff; if (low < 0x9f) { if (high < 0xa0) { high -= 0x81; high *= 2; high += 0x21; } else { high -= 0xe0; high *= 2; high += 0x5f; } if (low > 0x7f) low--; low -= 0x1f; } else { if (high < 0xa0) { high -= 0x81; high *= 2; high += 0x22; } else { high -= 0xe0; high *= 2; high += 0x60; } low -= 0x7e; } return (high << 8) | low; } /* get kanji font pointer */ static char *get_kanji_pointer(int sjis) { int kuten, ku, ten, idx; static int convert_keisen[] = { 0x0c45, 0x0c46, 0x0c41, 0x0c42, 0x0c44, 0x0c43, 0x0c48, 0x0c49, 0x0c4a, 0x0c47, 0x0c4b, 0x0c25, 0x0c26, 0x0c21, 0x0c22, 0x0c24, 0x0c23, 0x0c28, 0x0c29, 0x0c2a, 0x0c27, 0x0c2b, 0x0c35, 0x0c37, 0x0c39, 0x0c33, 0x0c3b, 0x0c55, 0x0c57, 0x0c59, 0x0c53, 0x0c5b, }; kuten = _mbcjmstojis(sjis) - 0x2020; /* convert keisen */ if (kuten >= 0x0801 && kuten <= 0x0820) { kuten = convert_keisen[kuten - 0x0801]; } ku = (kuten >> 8) & 0xff; ten = (kuten >> 0) & 0xff; idx = (ku - 1) * 94 + (ten - 1); return InData + OFFSET_KANJI + idx * KANJI_SIZE; } /* convert (Kanji) */ static void convert_kanji(char *filename) { int i, j, tnum; FILE *fp; FONTX2_KANJI f; tnum = sizeof(CodeTable_SJIS) / sizeof(FONTX2_CODETABLE); /* create header */ strncpy(f.h.identifier, "FONTX2", sizeof(f.h.identifier)); strncpy(f.h.fontname, FontName, sizeof(f.h.fontname)); for (i = 0; i < sizeof(f.h.fontname); i++) { if (f.h.fontname[i] < 0x20) f.h.fontname[i] = 0x20; } f.h.xsize = X_SIZE; f.h.ysize = Y_SIZE; f.h.codetype = CODETYPE_KANJI; f.tnum = tnum; /* save result */ fp = fopen(filename, "wb"); if (fp != NULL) { fwrite(&f, sizeof(f), 1, fp); fwrite(CodeTable_SJIS, sizeof(CodeTable_SJIS), 1, fp); for (i = 0; i < tnum; i++) { for (j = CodeTable_SJIS[i].start; j <= CodeTable_SJIS[i].end; j++) { fwrite(get_kanji_pointer(j), KANJI_SIZE, 1, fp); } } fclose(fp); } return; } /* convert (ASCII) */ static void convert_ascii(char *filename) { int i; FILE *fp; FONTX2_HEADER f; /* create header */ strncpy(f.identifier, "FONTX2", sizeof(f.identifier)); strncpy(f.fontname, FontName, sizeof(f.fontname)); for (i = 0; i < sizeof(f.fontname); i++) { if (f.fontname[i] < 0x20) f.fontname[i] = 0x20; } f.xsize = X_SIZE / 2; f.ysize = Y_SIZE; f.codetype = CODETYPE_ASCII; /* save result */ fp = fopen(filename, "wb"); if (fp != NULL) { fwrite(&f, sizeof(f), 1, fp); fwrite(InData + OFFSET_ASCII, OFFSET_KANJI - OFFSET_ASCII, 1, fp); fclose(fp); } return; } static void load_file(char *filename) { FILE *fp; memset(InData, ~0, sizeof(InData)); fp = fopen(filename, "rb"); if (fp != NULL) { fread(InData, 1, sizeof(InData), fp); fclose(fp); } } /* entry */ int main(int argc, char *argv[]) { if (argc < 4) { fprintf(stderr, "%s [infile] " "[outfile(ASCII)] [outfile(KANJI)]\n", argv[0]); goto fin0; } load_file(argv[1]); if (strncmp(InData, "FONT2 ", 8)) { fprintf(stderr, "file format error\n"); goto fin0; } X_SIZE = InData[11]; Y_SIZE = InData[13]; convert_ascii(argv[2]); convert_kanji(argv[3]); fin0: return EXIT_SUCCESS; }