/* --------- --------- --------- --------- --------- --------- --------- File: fanti_gb.c Daniel Chung. ~{oqFtR"~} (Fri, 1994-01-28, 1993equinox-11-10) Rearrange a Big-Five font file into a Guobiao file. Microsoft C 6.0. Before you use this file, make sure that you have the following: - Big5 font, "chinese.16.new" from FTP. Name this "chinese.16". Define B5_OFFSET to 773. - Guobiao font, any file will do. Name this "new.16". For /fg=0,9,14, define GB_OFFSET to (9 * 94). For /fg=0,7,14, define GB_OFFSET to (7 * 94). In general, for /fg=g1,g2,g3, use (((14 - g3) + (g2 - g1)) * 94). - Conversion table "hc.tab", and supplementary table "hc_supp.tab". They contain some errors today. However, these error conversions are ignored by my program and replaced by correct conversions. --------- --------- --------- --------- --------- --------- --------- */ #include #include #define TOP 4 #define MID 6 #define BOT 4 #define B5_OFFSET 773 /* skip in Big5 file before characters */ #define GB_OFFSET (9 * 94) /* skip in Guobiao file before characters */ char gb_filename[] = "new.16", /* Guobiao to be replaced */ b5_filename[] = "chinese.16"; /* "chinese.16.new" from FTP */ char table_file[] = "hc.tab", supp_file[] = "hc_supp.tab"; char converted['w'-'0'+1]['~'-'!'+1]; /* --------- --------- --------- --------- --------- --------- --------- arr_get: Get row from array. --------- --------- --------- --------- --------- --------- --------- */ unsigned int arr_get(unsigned char *arr, int row) { return arr[row * 2] << 8 | arr[row * 2 + 1]; } /* --------- --------- --------- --------- --------- --------- --------- arr_set: Set row into array. --------- --------- --------- --------- --------- --------- --------- */ void arr_set(unsigned char *arr, int row, unsigned int val) { arr[row * 2] = val >> 8; arr[row * 2 + 1] = val; } /* --------- --------- --------- --------- --------- --------- --------- gap_func: To fill gap when stretching character. --------- --------- --------- --------- --------- --------- --------- */ unsigned gap_func(unsigned top, unsigned bot) { return top & (bot | (bot>>1 & ~top>>1) | (bot<<1 & ~top<<1)); } /* --------- --------- --------- --------- --------- --------- --------- stretch: Stretch bitmap from 14 rows to 16 rows. --------- --------- --------- --------- --------- --------- --------- */ void stretch(unsigned char *arr) { int row; unsigned char new_arr[32]; unsigned int gap; /* top */ for (row = 0; row < TOP; row++) arr_set(new_arr, row, arr_get(arr, row)); /* gap */ gap = gap_func(arr_get(arr, TOP - 1), arr_get(arr, TOP)); arr_set(new_arr, TOP, gap); /* middle */ for (row = TOP; row < TOP + MID; row++) arr_set(new_arr, row + 1, arr_get(arr, row)); /* gap */ gap = gap_func(arr_get(arr, TOP + MID - 1), arr_get(arr, TOP + MID)); arr_set(new_arr, TOP + 1 + MID, gap); /* bottom */ for (row = TOP + MID; row < TOP + MID + BOT; row++) arr_set(new_arr, row + 2, arr_get(arr, row)); /* copy */ memcpy(&arr[0], &new_arr[0], 32); } /* --------- --------- --------- --------- --------- --------- --------- serif_func: Adjust serif of stretched character. --------- --------- --------- --------- --------- --------- --------- */ unsigned serif_func(unsigned self, unsigned top, unsigned bot) { return self & (self >> 1 | self << 1 | top | top >> 1 | top << 1 | ~(bot & (bot << 1 | bot >> 1)) ); } /* --------- --------- --------- --------- --------- --------- --------- serif_adj: Adjust serif of stretched character.. --------- --------- --------- --------- --------- --------- --------- */ void serif_adj(unsigned char *arr) { unsigned int self, top, bot; /* top gap */ top = arr_get(arr, TOP - 2); self = arr_get(arr, TOP - 1); bot = arr_get(arr, TOP + 1); self = serif_func(self, top, bot); arr_set(arr, TOP - 1, self); /* bottom gap */ top = arr_get(arr, (TOP+1+MID) - 2); self = arr_get(arr, (TOP+1+MID) - 1); bot = arr_get(arr, (TOP+1+MID) + 1); self = serif_func(self, top, bot); arr_set(arr, (TOP+1+MID) - 1, self); /* hanging from top gap */ bot = arr_get(arr, TOP - 1); self = arr_get(arr, TOP + 1); top = arr_get(arr, TOP + 2); self = serif_func(self, top, bot); arr_set(arr, TOP + 1, self); /* hanging from bottom gap */ bot = arr_get(arr, (TOP+1+MID) - 1); self = arr_get(arr, (TOP+1+MID) + 1); top = arr_get(arr, (TOP+1+MID) + 2); self = serif_func(self, top, bot); arr_set(arr, (TOP+1+MID) + 1, self); } /* --------- --------- --------- --------- --------- --------- --------- b5_load: Load Big5 bitmap from file. Chinese character only. --------- --------- --------- --------- --------- --------- --------- */ void b5_load(FILE *f, unsigned char byte1, unsigned char byte2, unsigned char *arr) { long index; index = (long) (byte1 - 0xA1) * 157 + (byte2 > 0x7F ? byte2-0xA0 + 0x7E-0x40 : byte2 - 0x40); fseek(f, (B5_OFFSET + (index - 3 * 157)) * 32, 0); fread(arr, 32, 1, f); } /* --------- --------- --------- --------- --------- --------- --------- gb_index: Given Guobiao code, return index. Chinese character only. --------- --------- --------- --------- --------- --------- --------- */ long gb_index(unsigned char c1, unsigned char c2) { long index1, index2, index = -1; index1 = c1 - '0'; index2 = c2 - '!'; if (index1 >= 0) index = GB_OFFSET + (long) index1 * 94 + index2; return index; } /* --------- --------- --------- --------- --------- --------- --------- gb_load: Load Guobiao bitmap from file. --------- --------- --------- --------- --------- --------- --------- */ void gb_load(FILE *f, unsigned char c1, unsigned char c2, unsigned char *arr) { long index = gb_index(c1, c2); if (index != -1) { fseek(f, index * 32, 0); fread(arr, 32, 1, f); } } /* --------- --------- --------- --------- --------- --------- --------- gb_save: Save Guobiao bitmap into file. --------- --------- --------- --------- --------- --------- --------- */ void gb_save(FILE *f, unsigned char c1, unsigned char c2, unsigned char *arr) { long index = gb_index(c1, c2); if (index != -1) { fseek(f, index * 32, 0); fwrite(arr, 32, 1, f); } } /* --------- --------- --------- --------- --------- --------- --------- copy_char: Copy character from Big5 file to Guobiao file. --------- --------- --------- --------- --------- --------- --------- */ void copy_char(FILE *old, FILE *new, unsigned char b5_1, unsigned char b5_2, unsigned char gb_1, unsigned char gb_2) { unsigned char arr[32]; /* big5 */ b5_load(old, b5_1, b5_2, arr); /* stretch to 16*16, temp */ stretch(arr); serif_adj(arr); /* guobiao */ gb_save(new, gb_1, gb_2, arr); } /* --------- --------- --------- --------- --------- --------- --------- copy_font: Copy Big5 font to Guobiao font, using table. --------- --------- --------- --------- --------- --------- --------- */ void copy_font(FILE *b5, FILE *gb, FILE *table) { unsigned char g1, g2, b1, b2; unsigned char line[81]; while (fgets(line, 80, table) != NULL) { if (line[0] == '#') continue; if (line[0] < '0' + 0x80) continue; g1 = line[0] - 0x80; g2 = line[1] - 0x80; b1 = line[2]; b2 = line[3]; if (!converted[g1 - '0'][g2 - '!']) { copy_char(b5, gb, b1, b2, g1, g2); converted[g1 - '0'][g2 - '!'] = 1; } } fclose(table); } /* --------- --------- --------- --------- --------- --------- --------- copy_err: Fix error in conversion tables. --------- --------- --------- --------- --------- --------- --------- */ void copy_err(FILE *b5, FILE *gb) { copy_char(b5, gb, 0xB0, 0xD1, 'H', '~'); /* ~{H~~} B0D1 san1 */ copy_char(b5, gb, 0xA4, 0x5C, 'g', '['); /* ~{g[~} A45C yao1 */ copy_char(b5, gb, 0xBB, 0xF2, 'C', '4'); /* ~{C4~} BBF2 me1 */ copy_char(b5, gb, 0xE2, 0xE9, 'X', ':'); /* ~{X:~} E2E9 */ copy_char(b5, gb, 0xF2, 0xA5, 'l', 'r'); /* ~{lr~} F2A5 */ } /* --------- --------- --------- --------- --------- --------- --------- main: Main function. --------- --------- --------- --------- --------- --------- --------- */ main() { FILE *gb_file, *b5_file, *table; gb_file = fopen(gb_filename, "r+b"); b5_file = fopen(b5_filename, "rb"); /* clear record of whether converted */ memset(converted, 0, sizeof(converted)); /* use original table */ table = fopen(table_file, "rt"); copy_font(b5_file, gb_file, table); fclose(table); /* use supplementary table */ table = fopen(supp_file, "rt"); copy_font(b5_file, gb_file, table); fclose(table); /* fix errors */ copy_err(b5_file, gb_file); fclose(gb_file); fclose(b5_file); }