Programming - cpueblo.com

[강좌] 한글 라이브러리 만들기


글쓴이 : 유광희 날짜 : 2002-05-13 (월) 21:20 조회 : 11426
번 호 : 2570 게시자 : 모기원 (jean94 ) 등록일 : 1998-01-04 20:56 제 목 : [강좌] 한글 라이브러리 만들기 #1 '한글 라이브러리' 제작 강좌 제 1 회 안녕하세요. 드디어 강좌를 시작합니다. 저는 예체능계(?)에 능력이 전혀 없는듯 해서... 화면을 깨끗하게 구성을 못합니다. 이 점 양해해 주세요~ 여기서 소개하는 한글 라이브러리는 100% C로 작성되었습니다. 최적화는 고려하지 않았구요..^^; 그만큼 속도가 떨어집니다. 하지만 제가 소개하는 것은 좋은 라이브러리가 아닌, 한글 출력의 개념입니다. ~~~~~~~~~~~~~~~~ 그럼 이제 본론으로 들어가죠. <--------------------------------------------------------------------------> 한글 코드는 영문코드와는 달리 2Bytes도 구성되어 있습니다. 한글은 초성, 중성, 종성으로 구성되어 있기 때문이죠. +-----------------------------------------------------------+ | bit : 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | | bin : 1 1 0 1 0 0 0 0 0 1 1 0 0 1 0 1 | | +--+--------------+--------------+--------------+ | | |F | 초 성 | 중 성 | 종 성 | | +-----------------------------------------------------------+ 표 1-1. 위의 표는 조합형 한글 코드입니다. bit 가 0 ~ 15까지 있는걸로 봐서 16비트, 즉 2Bytes겠죠? bin 부분은 2진수로 나타낸 것입니다. ( 16비트를 설명하기 위해서죠. ) F부분이 무엇이냐? 바로 한글과 영문을 구분하는 FLAG 입니다. flag부분이 1로 set되어있으면 한글을, 0이면 영문을 의미합니다. 그리고 뒷 부분은 5Bytes씩 초/중/종성을 나타냅니다. 그럼 초/중/종성의 코드를 알아야 겠죠? 초성은 19자, 중성은 21자, 종성은 27자로 구성 되어있습니다. +---------------------------------------------------------+ | 비트 초성 중성 종성 | 비트 초성 중성 종성 | |---------------------------------------------------------| | 00000 . . . | 10000 ?" . ?"?" | | 00001 FILL . FILL | 10001 ?" . ?" | | 00010 ?" FILL ?" | 10010 ?" ?끼 . | | 00011 ?" ?ㄲ ?" | 10011 ?" ?뇨 ?" | | 00100 ?" ?ⅱ ?"?" | 10100 ?" ?덩 ?"?" | | 00101 ?" ?│ ?" | 10101 . ?땁 ?" | | 00110 ?" ?㎖ ?"?" | 10110 . ?랙 ?" | | 00111 ?" ?Ð ?"?" | 10111 . ?륭 ?" | | 01000 ?" . ?" | 11000 . . ?" | | 01001 ?" . ?" | 11001 . . ?" | | 01010 ?" ?ア ?"?" | 11010 . ?빪 ?" | | 01011 ?" ?Б ?"?" | 11011 . ?샨 ?" | | 01100 ?" ?? ?"?" | 11100 . ?숱 ?" | | 01101 ?" ?? ?"?" | 11101 . ?쐼 ?" | | 01110 ?" ?? ?"?" | 11110 . . . | | 01111 ?" ?각 ?"?" | 11111 . . . | +---------------------------------------------------------+ 표 1-2. 휴..... 배끼기 힘드네요. ^^; 이 표를 외우실 필요는 전혀 없습니다. 그냥 보관하세요. 자... 이제 표까지 봤으니 표 1-1을 다시 볼까요? 15번 bit가 1로 set되어있으니 이후 코드는 한글이겠죠? 그럼 초성을 보세요. 10100 이죠? 표 1-2에서 찾아보면 '?"'이 나오구요. 중성은 00011이니까 '?ㄲ', 종성은 00101 이니까 '?"'이 되겠네요. 즉, 2Bytes를 조합해보면 "한" 이라는 글자가 됩니다. 쉽죠? 이 부분을 정확하게 이해를 하셔야 합니다. 잘 모르시는 분은 글자를 만들어서 계속 반복해 보세요. 전 머리가 나빠서 하루 종일 해서 알아냈는데...^^ 자... 그럼 2Bytes로 구성된 자료를 어떻게 보관하느냐...? union { unsigned ch; struct { unsigned jong : 5; unsigned jung : 5; unsigned cho : 5; unsigned bit : 1; } code; } h; C 문법을 공부하시면서 union을 보신적이 있으실 겁니다. 바로 여기서 사용되었죠. unsigned ch; 바로 요 부분에 글자가 들어갑니다. union이니까 당연히 code 구조체에도 같은 값이 들어가겠죠? ch에 글자를 넣어주면 초/중/종성의 코드가 자동적으로 들어가게 됩니다. 물론, bit 는 오토마타가 직접 1로 set해 줘야 겠죠. 이제 기본적인 출력 루틴을 볼까요? while( buf[i] ){ if( buf[i] & 0x80 ){ han_produre( buf, i ); han_putch( x, y, _hfont_buf ); x += 16; // 한글은 가로가 8 * 2 = 16 dot입니다. i += 2; // 2바이트이므로... } else { eng_produre( buf, i ); eng_putch( x, y, _efont_buf ); x += 8; i++; } } 출력 함수의 일부분 입니다. 잘 보세요. buf에는 문자열이 저장되어 있습니다. buf[i] & 0x80 는 한글인지 영문인지를 확인하는 부분입니다. 0x80은 2진수로 1000 0000 입니다. 즉, 15번 bit가 1인지를 확인하는 부분이 되겠군요. 여기서 한글로 판단이 되면 한글을 만들어 주는 함수에 문자열을 전달해 줍니다. 그리고 완성된 한글의 그림을 그려주면 되는거죠. 완성된 한글의 그림은 _hfont_buf에 저장됩니다. 영문은 _efont_buf이구요. char _hfont_buf[32], _efont_buf[16]; 아셨죠? 그럼 다음 부분을 봅시당~ 바로 han_produre함수죠. 이 함수는 한글 코드를 받아 그림을 완성 시키는게 주 임무죠. 백문이 불여일견....이라고 했으니... static void han_produre( char *str, int n ) { unsigned h1, h2, h3; h2 = ( unsigned )str[n] <&lt; 8; h3 = ( unsigned char )str[n + 1]; h1 = h2 + h3; han_make( h1 ); } 음...이런... 뭐가 뭔지 이해가 안되시는 분들이 꽤 많으실거라 생각 되네요. 자.. 하나씩 봅시다~ h2 = ( unsgned )str[n] &lt;&lt; 8; str에는 문자열이 있고 n에는 문자열의 포인터 위치가 있다는거 아시죠? hprintfpxy함수에서 넘겨줬습니다. 자, 생각해 보세요. 한글은 2bytes로 구성이 되어있습니다. 그럼 물론, str[n]에는 15~8번 bit가 있을테고... str[n + 1]에는 7~0번 bit가 있겠죠? 표 1-1을 떠올려 보세요. str[n]을 왼쪽으로 8번 shift를 해 준다는 의미... 표 1-1을 예로 들자면, 00000000 11010000 을 11010000 0000000으로 만든다는 뜻이죠. 그리고 h3 = ( unsigned )str[n + 1]... h1 = h2 + h3; 아시겠죠? 2Bytes로 구성된 문자열을 16bit인 unsigned 형으로 전환을 한 것이죠. 중요한 부분이니 그냥 넘어가시면 안됩니다. 종이에 써서 직접 해 보세요~ 제가 말 솜씨가 없어서 속 시원히 설명을 못해드리겠군요...^^; 어쨌든, unsigned 형으로 전환되어 h1에 저장한 데이타로 그림을 그립니다. static void han_make( unsigned ch ) { unsigned char first_b, middle_b, last_b, n1, n2, n3; int mid_start, las_start; switch( _hfontkind ){ case H8x4x4_FONT : mid_start = 160; las_start = 248; break; case H6x2x1_FONT : mid_start = 120; las_start = 164; break; case H2x1x2_FONT : mid_start = 40; las_start = 62; break; } h.ch = ch; n1 = han_table[0][h.code.cho]; n2 = han_table[1][h.code.jung]; n3 = han_table[2][h.code.jong]; first_b = ( n3 ? first[_hfontkind][1][n2] : first[_hfontkind][0][n2] ); middle_b = ( n3 ? middle[_hfontkind][1][n1] : middle[_hfontkind][0][n1] ); last_b = last[_hfontkind][n2]; if( n1 ) move_ch( _hfont[first_b * 19 + n1 + first_b], _hfont_buf, 32, COPY ); if( n2 ) move_ch( _hfont[mid_start + middle_b * 21 + n2 + middle_b], _hfont_buf, 32, OR ); if( n3 ) move_ch( _hfont[las_start + last_b * 27 + n3 + last_b], _hfont_buf, 32, OR ); } 와~ 복잡하다...........T_T 한글을 그려주는 부분은 이렇게 복잡한 반면에... 영문의 경우에는 단 한줄이면 됩니다. 억울....T_T 너무 많은것을 설명한듯 하네요. 위에 있는 han_make 함수는 다음에 설명해 드리죠. 복습을 잊지 마세요~ ^*^ &lt;--------------------------------------------------------------------------> 이번 강좌에서는 한글 코드의 구성, 한글 구별 방법, 형 전환까지 알아봤군요. 이번 강좌의 내용으로 한번 알고리즘을 그려보세요. 자신감을 갖고 부?씌혀 보는것이 중요합니다. 다른 사람이 알려주는 그대로 받아 들이지 마시고 자신에 맞게 변형을 해 보세요. 그것이 앞으로 많은 도움이 될겁니다. 그럼 다음에~~~~~~! 참고 서적 : '게임' 하듯이 게임 만들기, 재미있는 게임 프로그래밍, 번 호 : 2571 게시자 : 모기원 (jean94 ) 등록일 : 1998-01-10 17:45 제 목 : [강좌] 한글 라이브러리 만들기 #2 '한글 라이브러리' 제작 강좌 제 2 회 안녕하세요. 강좌가 많이 늦었군요. 강좌에 사용된 한글 라이브러리의 소스가 조금 수정되었습니다. 전에는 8x4x4, 7x2x3, 2x1x2 등 4개의 폰트를 지원했지만, 비 효율적인 알고리즘 때문에 8x4x4이외의 루틴은 삭제했습니다. 그 폰트를 다룰 강좌는 여기 부터 입니다. <----------------------------------------------------------------------------> 지난번에는 한글 폰트를조합하는 대략적인 루틴만을 보았습니다. 그런데 가장 중요한... 폰트를 읽어들이는 함수가 빠졌더군요..^^ char hread_font( char *han_file, char *eng_file ) { FILE *han, *eng; int i; if( han_file != NULL ){ if( ( han = fopen( han_file, "rb" ) ) == NULL ) return HAN_FERROR; fseek( han, _han_skip_byte, 0 ); for( i = 0 ; i < 360 ; i++ ) fread( &_hfont[i], 32, 1, han ); fclose( han ); } if( eng_file != NULL ){ if( ( eng = fopen( eng_file, "rb" ) ) == NULL ) return ENG_FERROR; fseek( eng, _eng_skip_byte, 0 ); for( i = 0 ; i &lt; 96 ; i++ ) fread( &_efont[i], 16, 1, eng ); fclose( eng ); } return NO_FERROR; } 한글과 영문 폰트를 화일로부터 읽어들입니다. 한글은 총 360자, 영문은 96자로 구성되어있습니다. 이것은, 폰트를 어떻게 구성하느냐에 따라 다르게 나타나는 값입니다. 제가 그린 폰트는 위와 같은 값입니다. ( 강좌가 끝나는데로 강좌를 정리하여 소스와 폰트 및 VFED를 올리겠습니다. ) ~~~~ * 제가 제작한게 아님니당~ 이 함수에서는 폰트를 읽어들여서 각각 _hfont와 _efont에 저장을 합니다. fread함수에서 한글은 32, 영문은 16이라고 쓴 부분은 한글은 영문의 두배의 크기이니 당연한 것이겠죠? 영문 폰트는 가로가 8도트이고 세로가 16도트입니다. 00000000 이렇게 나타내는 것이죠. 00011000 00111100 char형은 8비트입니다. 영문 폰트의 가로도 8도트, 이제 아시겠죠? 01100110 11000011 영문 도트의 한 줄을 char형으로 선언된 변수 하나에저장을 할 11000011 11111111 수 있습니다. 지난번 강좌를 잘 이해하셨다면 금방 아~~ 하실겁니다. 11111111 11000011 이렇게 해서, 영문 한글자는 8 * 16 bytes의 크기를 같습니다. 11000011 11000011 반면에, 한글은 가로 세로가 16도트로 표현되죠. 11000011 11000011 그래서 영문보다 두 배의 용량이 드는것입니다. 11000011 00000000 00000000 char _hfont[360][32], _efont[96][16]; 위와같이 선언된 이유를 아시겠죠? 여기까지는 어려운 부분이 없습니다. 이해가 안가셨다면, 다시 한번 읽어보세요. 지금부터 설명할 부분은, 한글의 자형 테이블 입니다. static unsigned char han_table[3][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 }, // 초성의 위치 { 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 }, // 중성의 위치 { 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 } // 종성의 위치 }; 위의 테이블이 의미하는 것은, 각 글자가 폰트에서의 위치입니다. 즉, 폰트 파일에는 '?" ?" ?" ?" ...' 순으로 자형이 저장되어 있습니다. 표 1-1을 떠올려 보세요. 초성에서 '?"'은 이진수로 00010 의 값을 갖습니다. 위의 테이블에서 찾아보면 그 값이 1이라는 것을 알 수 있죠? ex ) h = han_table[0][h.code.cho] ^ ^ | +--- 초성의 코드번호. +--- 초성 h.code.cho 가 '?"'의 값을 갖고 있다면 h는 1의 값을 갖습니다. h.code.cho 가 '?"'의 값을 갖고 있다면 h는 2의 값을 갖습니다. 바로 이 테이블에서 받은 값으로 그 글자가 폰트 테이블에서 몇번째 그림인지를 알아내는 것입니다. 그런데, 8x4x4 라는것이 무엇일까요? 초성이 8벌, 중성이 4벌, 종성이 4벌이라는 것입니다. '가' 에서의 '?"'과 '갑'에서의 '?"'은 생김새가 다릅니다. n벌 이라고 하는 것은, 한 글꼴에 대해서 n개의 그림이 있다는 의미입니다. 예로, 종성이 4벌이라고 한다면 다음과 같은 경우로 나누어집니다. * 중성에 따라 종성이 결정됩니다. 1분류 : ?ㄲ ?│ ?? 2분류 : ?Ð ?Б ?끼 ?땁 ?랙 ?숱 ?쐼 3분류 : ?ⅱ ?㎖ ?ア ?? ?각 ?랙 4분류 : ?? ?뇨 ?덩 ?빪 ?샨 ** 'C 프로그래밍 논리를 찾아라' 발췌. 폰트 파일을 보시면 아시겠지만, 초성 중성 종성 그리고 벌의 순서대로 그려집니다. " ?" ?" ?" ?" ....... ?" ?" ?" ?" ?" ....... ?" ?" ?" ?" ?" ....... " 이렇게 초성이 8벌 그려지고, 같은 방법으로 중성과 종성이 4벌씩 그려집니다. 그럼, 벌수 참조표를 알아봐야겠죠? 이 테이블은 han_table에서 읽어낸 값으로 참조합니다. static unsigned char first[2][22] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 2, 4, 4, 4, 2, 1, 3, 0 }, // 종성이 없을 경우 { 0, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 6, 6, 7, 7, 7, 6, 6, 7, 5 } }; // 종성이 있을 경우 static unsigned char middle[2][20] = { { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 }, // 종성이 없을 경우 { 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3 } }; // 종성이 있을 경우 static unsigned char last[22] = { 0, 0, 2, 0, 2, 1, 2, 1, 2, 3, 0, 2, 1, 3, 3, 1, 2, 1, 3, 3, 1, 1 }; 위의 테이블에 있는 값들은, 해당 글자가 몇번째 벌인지를 나타냅니다. n1 = han_table[0][h.code.cho]; 라고 해서 n1에 초성의 글자 위치를 알아냅니다. n3 = han_table[2][h.code.jong]; 여기서 n3의 값이 0이면 종성은 존재하지 않는 것입니다. 종성이 존재할 경우와 존재하지 않을 경우로 나누어서 벌수를 가려냅니다. first_b = ( n3 ? first[1][n2] : first[0][n2] ); first_b에는 초성이 몇번째 벌인지가 들어갑니다. 그럼 first_b와 n1으로 폰트 테이블에서 초성의 위치를 찾는것이죠. static void han_make( unsigned ch ) { unsigned char first_b, middle_b, last_b, n1, n2, n3; int mid_start = 160, las_start = 248; h.ch = ch; n1 = han_table[0][h.code.cho]; n2 = han_table[1][h.code.jung]; n3 = han_table[2][h.code.jong]; first_b = ( n3 ? first[1][n2] : first[0][n2] ); middle_b = ( n3 ? middle[1][n1] : middle[0][n1] ); last_b = last[n2]; if( n1 ) move_ch( _hfont[first_b * 19 + n1 + first_b], _hfont_buf, 32, COPY ); if( n2 ) move_ch( _hfont[mid_start + middle_b * 21 + n2 + middle_b], _hfont_buf, 32, OR ); if( n3 ) move_ch( _hfont[las_start + last_b * 27 + n3 + last_b], _hfont_buf, 32, OR ); } mid_start와 las_start는 중성과 종성이 테이블에서 시작되는 위치를 갖습니다. 그리고 아래에 있는 if( n1 ) ... 에서 if( n3) ... 까지는 폰트 테이블에서 그림을 읽어오는 부분입니다. move_ch함수는 각 그림을 _hfont_buf에 연산을 통해 옮겨주는 작업을 합니다. &lt;----------------------------------------------------------------------------> 자, 이번에는 여기서 끝내죠. 적은 내용이지만, 여기가 한글 출력 루틴의 핵심입니다. 제가 글솜씨가 없어서 쉬운 내용도 어렵게 설명이 된것 같네요.^^; 궁금하신 점은 게시판이나 메일로... 각 테이블의 기능을 잘 이해하셔야 합니다. 이 글을 올리는 즉시, 자료실에 폰트와 라이브러리 전체 소스 및 폰트 에디터를 업 로드할 것입니다. 참고 하세요. 번 호 : 2572 게시자 : 모기원 (jean94 ) 등록일 : 1998-01-16 00:30 제 목 : [강좌] 한글 라이브러리 만들기 #3 '한글 라이브러리' 제작 강좌 제 3 회 안녕하세요. 신년 인사를 나눌때가 어제 같은데, 벌써 16일 이네요. 이제 방학도 얼마 남지 않았네요. 한달만 더 쉬었으면...^^; ( 몇일만 자면 저도 수능을 보게 되네요..에구 무서버라~ ) 잡담이었습니다~! <----------------------------------------------------------------------------- > static void han_make( unsigned ch ) { unsigned char first_b, middle_b, last_b, n1, n2, n3; int mid_start = 160, las_start = 248; h.ch = ch; n1 = han_table[0][h.code.cho]; n2 = han_table[1][h.code.jung]; n3 = han_table[2][h.code.jong]; first_b = ( n3 ? first[1][n2] : first[0][n2] ); middle_b = ( n3 ? middle[1][n1] : middle[0][n1] ); last_b = last[n2]; if( n1 ) move_ch( _hfont[first_b * 19 + n1 + first_b], _hfont_buf, 32, COPY ); if( n2 ) move_ch( _hfont[mid_start + middle_b * 21 + n2 + middle_b], _hfont_buf, 32, OR ); if( n3 ) move_ch( _hfont[las_start + last_b * 27 + n3 + last_b], _hfont_buf, 32, OR ); } 지난번에는 이 함수를 하다 말았죠? 음....그러니까 이 함수는, 한글 글꼴을 완성하는 부분입니다. 폰트 테이블에서 글자 이미지를 읽어와서 결합 하는 부분이죠. static void move_ch( char *sor, char *dest, unsigned size, char bit ) { unsigned i; switch( bit ){ case COPY : for( i = 0 ; i < size ; i++ ) *dest++ = *sor++; break; case OR : for( i = 0 ; i &lt; size ; i++ ) *dest++ |= *sor++; break; } } 이건, 책에서 배꼈죠..^^; sor 에서 desk로 size만큼 복사하는 부분입니다. 그런데, 두 연산으로 나눠져 있죠. 0000000000000000 0000000000000000 0001111111110000 0000000000001100 0001111111110000 0000000000001100 0000000000110000 0000000000001100 0000000000110000 0000000000001100 0000000000110000 0000000000001100 0000000001100000 0000000000001111 0000000001100000 0000000000001111 0000000011000000 0000000000001100 0000000011000000 0000000000001100 0000000110000000 0000000000001100 0000000110000000 0000000000001100 0000001100000000 0000000000001100 0000011000000000 0000000000001100 0001100000000000 0000000000001100 0000000000000000 0000000000000000 자.... 위와 같은 두개의 이미지가 있다고 합시다. 왼 쪽은 'ㄱ' 이고, 오른쪽은 'ㅏ' 입니다. ㄱ + ㅏ = 가 그렇죠? 상상을 해보세요. 가로 세로 32 도트인 공간이 있습니다. 일단, 그 공간에 주인을 정해야 겠죠? 그 주인은, 초성으로 합니다. 초성은 그 공터에 그냥 COPY 하는거죠. 그럼 그 공간은 위 그림에서 왼쪽과 같은 모양을 하겠죠? 그럼 다음으로 중성을 넣어줍시다. 그런데, 중성마저 COPY로 밀어버리면? 그럼 안되죠~~~ 그래서 OR 연산을 하도록 한 것입니다. 1인 부분은 그냥 놔두고 0인 부분을 1로 바꿔주는거죠. 위의 함수를 보시면 금방 아시겠죠? 그럼.... han_make 함수에서는 한 글자의 이미지를 완전히 그려냈습니다. 이제 남은 일은... 화면에 찍어주는 일이죠. 화면에 찍어주는 일은 매우 간단합니다. static void han_putch( int x, int y, char *ch ) { int i, j = 0, temp, n, m, xx, yy; xx = _mag_x &lt;&lt; 3; yy = _mag_y &lt;&lt; 4; hy = y; while( j &lt; yy ){ temp = j; for( i = 0 ; i &lt; 2 ; i++ ){ j = temp; m = i * xx; for( n = 0 ; n &lt; _mag_y ; n++ ) dot( x + m, y + j++, *( ch ) ); *( ch++ ); } j = temp + _mag_y; } } 이 함수는 완성된 글자 이미지를 와면에 뿌려주는 부분입니다. _mag_x, _mag_y 변수는 신경쓰지 마세요. 글자를 정수배 확대하기 위해서 만든 변수이니까요. 각 변수에 n의 값을 넣어주면 그만큼 확대되어 출력이 되는거죠. 하지만, 지금은 _mag_x = _mag_y = 1 이라고 생각하세요. 한글은 영문과는 달리 가로가 32도트라고 했습니다. 그러니 처음 16도트를 출력하고 다음으로 16도트를 출력해야 합니다. 소스를 하나 하나 집어 나가시면 아시겠지만, 영문 두 글자를 출력하는 듯이 처리 합니다. 즉, 16 * 16 도트를 먼저 출력합니다. 가로 ( 0 ~ 15 ) 도트입니다. 다음으로 16 * 16도트를 출력합니다. 가로 ( 16 ~ 31 ) 도트입니다. 'ㅁ'을 출력한다고 하면... 00000000 00000000 00000000 00000000 00111111 11111100 00111111 11111100 00110000 00001100 00110000 00001100 00110000 00001100 00110000 00001100 00110000 00001100 00110000 00001100 00110000 00001100 00110000 00001100 00111111 11111100 00111111 11111100 00000000 00000000 00000000 00000000 한글은 이렇게 두 부분으로 나누어 집니다. 그래서 왼쪽이 먼저 출력되고 다음으로 오른쪽이 출력되는 것이죠. han_putch함수를 잘 봐두시기 바랍니다. static void dot( int x, int y, char ch ) { int table[8] = { 128, 64, 32, 16, 8, 4, 2, 1 }; int i = 0, j = 0; for( j = 0 ; j &lt; 8 ; j++ ){ for( i = 0 ; i &lt; _mag_x ; i++ ){ if( ch & table[j] && _fcolor != _hspr_color ) putpixel( screen, x + i, y, _fcolor ); else if( _bcolor != _hspr_color ) putpixel( screen, x + i, y, _bcolor ); } x += _mag_x; } } 이 함수가 바로 화면에 찍어주는 부분입니다. 이 함수가 바로 이 라이브러리의 최종 행선지인 셈입니다. table변수를 보죠. 128은 2진수로 1000 0000 입니다. 64는 0100 0000 32는 0010 0000 16은 0001 0000 8은 0000 1000 4는 0000 0100 2는 0000 0010 1은 0000 0001 아셨죠? 그럼 다음부분으로 넘어가죠. 여기에 사용된 _mag_x 변수 역시 1의 값으로 보세요. for( j = 0 ; j &lt; 8 ; j++ ){ 가로가 8도트이기 때문이죠. for( i = 0 ; i &lt; _mag_x ; i++ ){ if( ch & table[j] && _fcolor != _hspr_color ) putpixel( x + i, y, _fcolor ); else if( _bcolor != _hspr_color ) putpixel( x + i, y, _bcolor ); } ch에는 8 도트의 정보가 들어있습니다. 그래서 ch & table[j] 로 글자 부분인지 배경 부분인지를 알아내는 것이죠. 글자부분이면 글자 색으로.. 배경 부분이면 배경 색으로....^^; * 여기서 putpixel 함수는 정의하지 않았습니다. &lt;----------------------------------------------------------------------------> 자...이제 여행은 끝났습니다. 한글 출력 루틴만 알아봤지만 영문은 8*16 도트이니 매우 쉽죠. 연산할 필요도 없구요.. 하지만, 소스에서 한번쯤은 봐 두세요. 어려운 부분을 제대로 설명하지 못한점이 많은것 같네요. 제가 아직 글솜씨가 없어서...T_T 이것으로 강좌는 마칩니다. 다음에는 한글 출력 라이브러리 에 주석을 달아서 정리한 것을 올리겠습니다. 그럼 이만~ ps. 새해 복 많이 받으세요.