/* * Han2gd.c * * made by scgyong@nownuri.net * * you can modify and redistribute this source * under the rule of Copy-Left, GNU */ #include #include #include // for gd library #include #define MAXLINEWIDTH 80 #define BUFWIDTH (MAXLINEWIDTH + 2) #define MAXHEIGHT 10 #define MAXGIFWIDTH (8*BUFWIDTH) #define MAXGIFHEIGHT (16*MAXHEIGHT) #define CHAR_ON '0' #define CHAR_OFF ' ' typedef enum { FALSE, TRUE } BOOL; typedef unsigned short WORD; typedef unsigned char BYTE; #define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) #define LOBYTE(w) ((BYTE)(w)) #define MAKEWORD(a, b) \ ((WORD) (((BYTE) (a)) | ((WORD) ((BYTE) (b))) << 8)) #define HAN_FIR(w) (((w) >> 10) & 0x1F) #define HAN_MID(w) (((w) >> 5) & 0x1F) #define HAN_LAS(w) ( (w) & 0x1F) #define OFFSET_MID (20 * 8) #define OFFSET_LAS (OFFSET_MID + 22 * 4) static char szHFileName[] = "hangul.fnt"; static char szEFileName[] = "english.fnt"; static unsigned short hfont[8*20 + 4*22 + 4*28][16]; static unsigned char efont[96][16]; static gdImagePtr img; static int paint, white; static int chSaved; static int nChar; static int cyChar; static int dirty_left; static int dirty_top; static int dirty_right; static int dirty_bottom; static int color = 0; static const int nFirTable[32] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const int nMidTable[32] = { 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 12, 13, 14, 15, 16, 17, 0, 0, 18, 19, 20, 21, 0, 0 }; static const int nLasTable[32] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0 }; static const int nFirRef[22][2] = { 0, 0, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 1, 6, 3, 7, 3, 7, 3, 7, 1, 6, 2, 6, 4, 7, 4, 7, 4, 7, 2, 6, 1, 6, 3, 7, 0, 5 }; static const int nMidRef[20] = { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 }; static const int nLasRef[22] = { 0, 0, 2, 0, 2, 1, 2, 1, 2, 3, 0, 2, 1, 3, 3, 1, 2, 1, 3, 3, 1, 1 }; BOOL LoadFont(char *szFileName, void *dest, int cbSize) { FILE *pFile; int ret; pFile = fopen(szFileName, "rb"); if (!pFile) { printf("Font File %s Open Error\n", szFileName); return FALSE; } ret = fread(dest, cbSize, 1, pFile); fclose(pFile); return ret ? TRUE : FALSE; } BOOL InitProgram(void) { BOOL ret; int r, g, b; ret = LoadFont(szHFileName, hfont, sizeof (hfont)); if (!ret) return FALSE; ret = LoadFont(szEFileName, efont, sizeof (efont)); if (!ret) return FALSE; img = gdImageCreate(MAXGIFWIDTH, MAXGIFHEIGHT); if (!img) return FALSE; r = color % 256; g = (color / 256) % 256; b = color / 256 / 256; paint = gdImageColorAllocate(img, r, g, b); white = gdImageColorAllocate(img, 0xFF, 0xFF, 0xFF); return TRUE; } BOOL DestroyBuffer(void) { if (img) { gdImageDestroy(img); } return TRUE; } BOOL PrintBuffer(void) { int cx, cy; gdImagePtr nimg; if (dirty_left > 0) dirty_left--; if (dirty_top > 0) dirty_top--; if (dirty_right < MAXGIFWIDTH) dirty_right++; if (dirty_bottom < MAXGIFHEIGHT) dirty_bottom++; cx = dirty_right - dirty_left + 1; cy = dirty_bottom - dirty_top + 1; nimg = gdImageCreate(cx, cy); if (!nimg) { return FALSE; } gdImageCopy(nimg, img, 0, 0, dirty_left, dirty_top, cx, cy); //gdImagePng(nimg, stdout); gdImageGif(nimg, stdout); gdImageDestroy(nimg); return TRUE; } BOOL ClearBuffer(void) { gdImageFilledRectangle(img, 0, 0, MAXGIFWIDTH, MAXGIFHEIGHT, white); dirty_left = MAXGIFWIDTH; dirty_top = MAXGIFHEIGHT; dirty_right = 0; dirty_bottom = 0; nChar = 0; return TRUE; } BOOL SetBufOn(int x, int y) { int img_x = nChar * 8 + x; int img_y = cyChar * 16 + y; gdImageSetPixel(img, img_x, img_y, paint); if (dirty_left > img_x) dirty_left = img_x; if (dirty_right < img_x) dirty_right = img_x; if (dirty_top > img_y) dirty_top = img_y; if (dirty_bottom < img_y) dirty_bottom = img_y; return TRUE; } BOOL CheckForLineEnd(int nWidth) { nChar += nWidth; if (nWidth <= 0 || nChar >= MAXLINEWIDTH) { nChar = 0; cyChar++; if (cyChar >= MAXHEIGHT) { return FALSE; } } return TRUE; } BOOL PutSingleByte(int ch) { int src, x, y; if (ch == '\n') { return CheckForLineEnd(0); } if (ch < 32) { ch = 32; } ch -= 32; for (y = 0; y < 16; y++) { src = efont[ch][y]; for (x = 0; x < 8; x++) { if (src & 0x80) SetBufOn(x, y); src <<= 1; } } if (!CheckForLineEnd(1)) { return FALSE; } return TRUE; } static BOOL memor(unsigned short *dest, unsigned short *src) { int i = 16; while (i--) { *dest++ |= *src++; } return TRUE; } BOOL PutDoubleByte(int wChar) { unsigned short buf[16]; int src, x, y; int cfir, cmid, clas; int ofir, omid, olas; int mfir, mmid, mlas; // // counters // cfir = nFirTable[HAN_FIR(wChar)]; cmid = nMidTable[HAN_MID(wChar)]; clas = nLasTable[HAN_LAS(wChar)]; // // index offsets // ofir = nFirRef[cmid][clas != 0]; omid = nMidRef[cfir] + (clas ? 2 : 0); olas = nLasRef[cmid]; // // memory offsets // mfir = ofir * 20 + cfir; mmid = omid * 22 + cmid; mlas = olas * 28 + clas; if (cfir) { memcpy(buf, hfont[mfir], 32); } else { memset(buf, 0, 32); } if (cmid) { memor(buf, hfont[mmid + OFFSET_MID]); } if (clas) { memor(buf, hfont[mlas + OFFSET_LAS]); } for (y = 0; y < 16; y++) { // change byte order src = MAKEWORD(HIBYTE(buf[y]), LOBYTE(buf[y])); for (x = 0; x < 16; x++) { if (src & 0x8000) SetBufOn(x, y); src <<= 1; } } if (!CheckForLineEnd(2)) { return FALSE; } return TRUE; } BOOL PutChar(int ch) { BOOL ret = TRUE; if (chSaved) { ret = PutDoubleByte(MAKEWORD(ch, chSaved)); chSaved = 0; } else if (ch & 0x80) { chSaved = ch; } else { ret = PutSingleByte(ch); } return ret; } int main(int argc, char *argv[]) { int ch; if (argc > 1) { color = atoi(argv[1]); if (color < 0 || color > 0x00FFFFFF) { color = 0; } } if (!InitProgram()) { printf("Program Initialization Error\n"); exit(0); } ClearBuffer(); while ((ch = getchar()) != EOF) { if (!PutChar(ch)) { break; } } PrintBuffer(); DestroyBuffer(); return 0; }