C언어 > [펌] 조합형 한글 출력하기

TODAY1,211 TOTAL684,081
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | C언어 | C언어 | [펌] 조합형 한글 출력하기

페이지 정보

작성자 키트 작성일2017-09-12 11:39 조회580회 댓글0건

본문

 

[펌] 조합형 한글 출력하기..

by lazysoul on Aug.10, 2005, under Uncategorized

출처 : 너바나(재광)님의 블로그

 

이곳 저곳을 돌아다니다가 필요한 글을 허락도 없이 가져왔네요.. ^^
             
             
  제목 : IAR사 64180-C Compiler를 이용한 펌웨어 구축기법 (4)
  작성 : 손민철 ( 하이텔:xsnake / 천리안:mcson / E-mail:mcson@chollian.net )
        이 파일은 천리안과 하이텔 디동에 공통으로 업로드될 예정이다
        게시되지 못하는 것은 내 책임이 아니다.. 시솝의 고유 권한이기 때문이다
  날짜 : 99년 11월
—————————————————————————————
 
 
  7. 한글 관련 프로그래밍의 기초 : 폰트 핸들링

    국내의 한글 프로그래밍은 멀리 APPLE컴퓨터와 MSX기종이 그 발전의 초석을
    마련했씀을 부인하는 사람은 없을 것이다. 가장 절정을 이룬 것은 아무래도
    이찬진씨나 한글도깨비의 공로라 아닐 수 없으며 이후 실력있는 프로그래머가
    과감하게 한글 라이브러리 관련 소스들을 공개해줌으로써 가능해지지 않았나
    생각한다.

    실제로 콘트롤러상에서 한글을 사용하는 부분은 LCD와 키보드 작업, 통신작업
    등 전반적인 부분을 점유하며 콘트롤러 펌웨어를 구축하는 사람에게는 엄청난
    상수집단( 폰트데이타가 모두 상수이다 )을 처리해야하는 골치아픈 문제로 대
    두된다.  이것을 깔끔하게 처리하는 분들은 대단히 상업적인 프로그래머로 일
    개 개발회사의 사장님이거나 대단히 핵심적인 위치에 있는 분인 경우가 많다.

    이런 폰트 핸들링 기법은 PC에서는 한글 라이브러리를 만드는 기술 정도보다
    약간 고난도인데 조금 C로 짜다가 속도가 나오지 않으면 어셈으로 전환해야함
    은 말할 필요도 없다.  조금 콘트롤러 자원이 여유가 있고 가격이 맞는다면
    폰트롬을 사용하는 것도 좋은 방법이지만, 콘트롤러 버스의 여유가 대부분은
    없을 것이고 소프트웨어적으로 처리하는 것이 비용을 절감하는 것이 된다.

    즉, 다른 얘기를 하자면 LCD를 쓰는 콘트롤러를 만든다고 하면 제작자는 무
    조건적으로 한글관련 프로그래밍 기법을 연구해야 한다. 이것만이 제품의 부
    가가치를 창출하는 유일한 방법이기 때문이다.

    그런데 문제가 있다. 그 놈의 대학교나 대학원에서 이런 한글관련 제어기술을
    체계적으로 가르쳐주지 않는다는 것이다. 오로지 프로그래머의 자원에만 의존
    한다. 참으로 어이가 없다. 프로그래머는 무슨 땅을 팔아서 장사를 하느냐는
    거다. 다 공부를 하고 트레이닝을 거쳐야만 프로그램을 구축할 수 있다는 것을
    업체의 대표가 간과한다는 것이다. 물론 투자를 엄청하고도 별볼일 없는 자원
    을 보유하게 되는 것도 문제가 있긴 하다.  그런거 공부하여 부가가치를 창출
    했는데도 전혀 인정이 않된다는 사실이다. 의례 콘트롤러 설계자는 내장 펌웨
    어도 직접짜야하고 그래픽 LCD가 있다면 당연히 한글을 자유롭게 입출력하는
    것으로 간주하고 있다.  그러다 보니 하드웨어 개발자는 무조건 경력자만 우
    대받고 더이상 발전이 않되는 정체성을 지니는 악순환을 지금까지도 되풀이하
    고 있는 것이다.  나는 개인적으로 전문적인 하드웨어 교육을 담당하시는 분
    들이 한글관련기술에 좀더 정성을 들인다면 교육을 바로 마친 학생이라도 상
    업적인 제품을 개발하는데 자신을 가지지 않을까 생각하다.

    전혀 겁을 먹을 필요가 없다. 앞서 전제한 iccz8003.txt 에서 엄청난 상수집
    단을 처리하는 기법에 대해서 언급을 했고 역시 이전의 문서에서 LCD에 인터
    페이스를 붙이는 방법도 기술했으니 이글을 계속 읽으신 분이라면 어떠한 LCD
    라도 매뉴얼만으로도 분명히 응용을 하실 수 있을 것이라고 생각한다.
    약간의 준비작업이 필요하다
    ————————–

       – FED.EXE 는 이찬진씨가 아래아한글 개발전에 마소를 통해서 소스를
         풀로 공개했다. ( 이 소스에 약간 에러가 있긴 하다 ) 또한 이후에
         채희선이란 분이 다시 이소스의 버그를 고쳐 “퍼스날컴퓨터”지에
         EDITOR.EXE 를 제작해서 공개했다.  아래아한글 구형 버전에 있는
         FED.EXE 를 쓰셔도 되며 기타 폰트에디터를 구해야 한다.

       – 통신망 자료실에 보면 폰트들은 대단히 많다. 상업적으로 쓸 수 있는
         폰트는 “고딕체”가 무난할 듯하다.

         이때 가능하면 초보자는 8X4X4 (초성 8벌 , 중성 4벌, 종성 4벌 )짜리
         를 구하면 된다. 대개 폰트들은 8X4X4벌식의 구조를 지닌다.  약간
         상업적인 폰트를 쓰기위해서 이야기에 내장된 폰트를 쓰시는 분들이
         있을 것 같다.  폰트에디터로 살펴보면 폰트제작에 대단히 정성을 들인
         구조를 발견한다.  즉, 상수집단을 가능한 줄인다는 기술이다. 이것은
         폰트를 어떻게 디자인하는냐에 따라  7X2X2 벌식으로도 대단히 미려한
         한글을 구현할 수 있다. 2X1X2벌식의 경우엔 말그대로 도깨비체라 하여
         메모리를 줄일 수는 있겠지만 글자가 삐뚤빼뚤한 빨래꼴의 글자이상을
         기대할 수가 없다.

         사실상 이야기의 글꼴을 능가하는 글꼴은 없고 이들 글꼴을 사용하면
         이야기 개발자에게 저작권료를 지불해야 하겠지만 돈이 쥐꼬리만한 예
         산으로 콘트롤러를 개발하는 사람에게 무슨 그런 엄청난 힘이 있나..
         나쁘게 말하자면 도용하는 수밖에 없을 것이다.  ( ^^; )
    자신만의 유틸리티를 제작할 수 있는 도스용 툴이 필요하다
    ——————————————————-

       -  퀵베이식이나 터보C, 볼랜드C++3.1 이 있으면 좋겠다.

          “엥? 윈도우즈 시대에 웬 도스용 개발툴…? ” 이라고 말을 하시는
          분은 막강한 자신의 윈동즈용 컴파일러를 써도 상관없다. 하지만
          분명히 효율은 떨어질 것같다.  하루가 시급한 콘트롤러 개발자가
          개발하다가 윈도우용 델파이나 비주얼C를 만진다고 하면 사장이 가
          만 놔둘까? ( 분명 한소리 들을 것이다 )

          개인의 취향이므로 아무거나 파일을 핸들링할 수 있는 유틸리티를
          만들 수 있는 것이면 아무거나 된다.
    자 폰트를 데이터로 읽어보자
    —————————-
      보통 16X16 사이즈의 한글 폰트 화일이고 별도의 헤더가 붙지 않았다면
      크기가 11520 바이트의 BIN형태의 파일일 것이다.
      하드웨어 개발자는 보통 헥사<->바이너리 전환 유틸리티가 있으므로 아
      주 간단하게 헥사코드를 잡아낼 수 있을 것같다.  귀찮으면 다음과 같은
      소스로 아주 간단하게 az80 어셈블러의  소스를 생성할 수 있다.

      16X16 한글 폰트 한개가 32바이트이기에 아주 간단히 읽어낸다.
      #include <stdio.h>
      #include <conio.h>

      void main(void)
      {
        int i,j,k;
        FILE *a;
        i=j=k=0;
        a=fopen(“hangul.fnt”,”rb”);
        printf(”   defb    “);
        YY:;
        i=getc(a);
        if(i != EOF){
           if(j<31)printf(“%3d,”,i);
           else    printf(“%3d”,i);
           j++;
           if(j==32){
              printf(“\n   defb    “);
              j=0;
           }
           goto YY;
        }
        fclose(a);
      }

      위의 파일을 컴파일해서 가령 makesrc.exe 로 만들었다면
      도스 커맨드 라인에서
      makesrc > temp.s01

      명령어로 아주 간단히 소스를 생성시킨다. ( 아마 이제껏 이걸 몰라서
      열심히 텍스트에디터로 편집하시던 분은 약간 허탈해하실 것 같다 )
      초성,중성,종성별로 분리하는 것도 간단하다.

      보통 11520바이트짜리 폰트 파일은 다음의 구조이다.

      초성 20자: SP ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ     : 8 세그먼트
      중성 22자: SP ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ : 4 세그먼트
      종성 28자: SP ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅃㅅㅆㅇ : 4 세그먼트
                 ㅈㅊㅋㅌㅍㅎ

      SP = SPACE BAR

      초성 8벌 =     0 ~  5119 ( 20 X 8 X 32 )
      중성 4벌 =  5120 ~  7935 ( 22 X 4 X 32 )
      종성 4벌 =  7936 ~ 11519 ( 28 X 4 X 32 )

      등으로  초성,중성,중성 오프셋번지를 알아낼 수 있는 것이다.
      좀더 오프셋을 세분화시키는 것도 가능할 것이다. ( 그건 알아서… )
      영문폰트는 한글 폰트의 절반 크기로 8X16 크기이므로
      내부 수치만 바꿔주면 된다.
      #include <stdio.h>
      #include <conio.h>

      void main(void)
      {
        int i,j,k;
        FILE *a;
        i=j=k=0;
        a=fopen(“english.fnt”,”rb”);
        printf(”   defb    “);
        YY:;
        i=getc(a);
        if(i != EOF){
           if(j<15)printf(“%3d,”,i);
           else    printf(“%3d”,i);
           j++;
           if(j==16){
              printf(“\n   defb    “);
              j=0;
           }
           goto YY;
        }
        fclose(a);
      }

      +——————————————————————–+
      |                                                                    |
      | 여기에서 우스운 얘기 하나 해보자                                   |
      |                                                                    |
      | 예전에 모 업체에 놀러갔을 떄 상기 이 작업을 모두 수작업으로        |
      | 다음과 같이 하고 있었다                                            |
      |                                                                    |
      |                                                                    |
      | rename hangul.fnt hangul.bin                                       |
      | hexbin hangul.bin hangul.hex                                       |
      |                                                                    |
      | 열심히 텍스트에디터로 인텔헥사 파일을 편집중.. (꼬박 2시간 소요)   |
      | 헥사코드를 열심히 계산기를 두들겨서 10진수로 변환 ( 꼬박 이틀 )    |
      |                                                                    |
      | 나는 옆에서 이런 잔인한 생각을 해봤다.. ( 오타가 있다면…? )      |
      |                                                                    |
      |                                                                    |
      +——————————————————————–+
      az80 어셈블러는 이상하게 헥사값 7fh 이상의 값을 defb로 저장할 수가
      없기에 십진수로 통일하면 이상없이 저장이 되고 있다.  아마 최근에
      나오는 것은 이 문제를 해결하지 않았을까 생각한다.  어쩄튼 위의 방법
      으로 쓸데없이 폰트를 헥사로 변환하는 일은 하지 않아도 된다.
      상기 소스는 해당 함수를 교체하여 도스용 QBASIC으로도 아주 간단하게
      만들 수 있을 것 같다.
      막바로 바이너리 파일을 소스화하니까 넘 좋다!
      ——————————————–
      다음은 베이식동호회인가 소프트동호회에서 퀵베이식용 한글 라이브를
      만든 경험이 많으신 “김성익”씨의 글을 캡쳐한 것입니다.
      대단히 발전된 형태의 한글 출력 소스를 접할 수 있을 겁니다.

       김성익   (NOERROR )
      [단편] 한글출력제어                          07/01 02:18   338 line

         안녕하세요.김성익(NOERROR)임니다.간단히 한글 출력에 대해 글을 써
       내려가 보도록 하겠습니다.  자세한 응용은 각자 해보시길 바라고 여기
       선 16×16크기로 8x4x4벌 한글폰트를 출력하는 꼴만을 기준으로 설명 드
       리지요.

       1. 한글구성

         아주 기본적인 거지만 간단히 집고 넘어가겠습니다.                                          xsnake / mcson / 뱀띠아찌

         한글은 초성,중성,종성으로 이루어져 있습니다.( ‘김’이란 글자의 경
       우 초성은 ‘ㄱ’,중성은 ‘ㅣ’,종성은 ‘ㅁ’이 되겠죠.)

         초성 19자:ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
         중성 21자:ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
         종성 27자:ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅃㅅㅆㅇㅈㅊㅋㅌㅍㅎ

       로  이루어져 있습니다.

         한글폰트는 초성,중성,종성별 데이타로  구성되어 있고  출력시엔 각
       해당부분끼리 합성해서 완성된 형태를 출력합니다. 만약 일일이 합성된
       한글로 구성해서 폰트를 만든다면 폰트적재만으로 메모리가 모자라겠죠
       ? ( 모 잡지에 어떤 대회 대상 수상자분께서  한글을 메모리땜에  넣지
       않았다는 코메디성발언을 하신적이 있지요. 아! 우수워…. 대상이라니
       .. 제가 알기론 모잡지는 상당히 권위가 있는 잡지인 데…쩝)

         글자 조합 형태는 초성+중성, 초성+중성+종성 2종류로 나눌수 있습니
       다.

       2. 한글코드

         한글은 다들 아시다시피 2byte로 구성되어 있습니다.2byte에 초성,중
       성,종성코드가 들어 있지요. 조합형문자의 구성을 알아보도록하죠.

          76543210  76543210
          x                  : 한글코드임을 나타냄
           xxxxx             : 초성
                xx  xxx      : 중성
                       xxxxx : 종성

         그럼 간단히 한글 코드를 이용해 초성,중성,종성으로 분류하는  루틴
       을 짜보죠.

         void puthan(unsigned code)
         {
           unsigned char first;  /* 초성 */
           unsigned char middle; /* 중성 */
           unsigned char last;   /* 종성 */

           first=(code>>10)&31;
           middle=(code>>5)&31;
           last=(code)&31;
           ..
         }

         그런데 무신 이유에서인지 초성이나 중성,종성 모두 각 자별로 순차
       적으로 들어 있는 것이 아니라 “ㄱ,ㄲ,..”을 순서대로 1,2,3,..의  번
       호를 매길수가 없습니다.(중간에 사용하지 않는 부분이 있어서…) 그
       래서 간단히 테이블처리를 하면 순서대로 처리할수 있습니다.

         unsigned char _first[]={
              0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
              };
         unsigned char _middle[]={
              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
              };
         unsigned char _last[]={
              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
              };

         void puthan(unsigned code)
         {
           … /* 앞의 내용 */

           first=_first[first];
           middle=_middle[middle];
           last=_last[last];

           …
         }

         이렇게 하면 first,middle,last에 각 글자의 데이타가 들어가게 되
       죠.이제는 각 해당 폰트를 합성해서 출력하기만 하면 됨니다.

       3. 한글벌수

         한글출력루틴을 만드는 것이 어려운건 아니지만 다들  폰트와의 연
       개부분(벌수조정)에서 어려움을 느끼고 포기하곤 하죠.하지만 그다지
       어려운 내용도 아님니다.

         다들 아시겠지만 한글출력이 단순히 초성,중성,종성만을  합성하는
       것이 아님니다.  간단한 예로 같은 초성 ‘ㄱ’의 경우 ‘갬’,'그’의 초
       성모양을 비교해 보세요.완전히 다름니다. ‘갬’에서 쓰이는 초성모양
       으로 ‘그’를 만든다면 상당히 부자연스럽겠죠?

         그래서 미려한 글자를 위해 여러가지 글자조합방식을  연구했는 데
       ….  그중에서 가장 대중적인 것이 8x4x4나 10x4x4벌식의 한글이죠.
       (어떤분이 첨에 쓰셨는 지는 알수없지만 조금씩 낳은 모양,낳은 구조
       로 발전하다가 결국 이런 형태로 굳어져 대부분 이런 구조로  폰트를
       만드는 거겠죠.)

         여기선 8x4x4에 대해 알아보죠.

         8x4x4벌이란 초성 8벌,중성 4벌,종성 4벌을 나타냄니다.각 벌의 구
       성을 알아보죠.그럼 아마 벌이란 무엇인지 아실검니다.

        초성
            초성 1벌 : 받침없는 ‘ㅏㅐㅑㅒㅓㅔㅕㅖㅣ’ 와 결합
            초성 2벌 : 받침없는 ‘ㅗㅛㅡ’
            초성 3벌 : 받침없는 ‘ㅜㅠ’
            초성 4벌 : 받침없는 ‘ㅘㅙㅚㅢ’
            초성 5벌 : 받침없는 ‘ㅝㅞㅟ’
            초성 6벌 : 받침있는 ‘ㅏㅐㅑㅒㅓㅔㅕㅖㅣ’ 와 결합
            초성 7벌 : 받침있는 ‘ㅗㅛㅜㅠㅡ’
            초성 8벌 : 받침있는 ‘ㅘㅙㅚㅢㅝㅞㅟ’

        중성
            중성 1벌 : 받침없는 ‘ㄱㅋ’ 와 결합
            중성 2벌 : 받침없는 ‘ㄱㅋ’ 이외의 자음
            중성 3벌 : 받침있는 ‘ㄱㅋ’ 와 결합
            중성 4벌 : 받침있는 ‘ㄱㅋ’ 이외의 자음

        종성
            종성 1벌 : 중성 ‘ㅏㅑㅘ’ 와 결합
            종성 2벌 : 중성 ‘ㅓㅕㅚㅝㅟㅢㅣ’
            종성 3벌 : 중성 ‘ㅐㅒㅔㅖㅙㅞ’
            종성 4벌 : 중성 ‘ㅗㅛㅜㅠㅡ’

         대충 감을 잡으셨겠죠? 폰트가 다음과 같이 구성되어 있습니다. 폰
       트에디터같은 걸로 보시면 초성문자 8묶음,중성 4묶음,종성 4묶음 씩
       되어 있을 텐데… 각 묶음은 위와 같은 조건으로 그림거지요.  그럼
       출력루틴을 만들어 보지요.

       4. 벌수 분석

         이제 한글 출력을 위한 모든 자료는 모였다고 볼수있습니다.  이제
       출력을 위해 글자를 합성하기만 하면 되죠.앞에서 각 구성 코드로 나
       누는 부분을 짜 보았고 이제 각 초성,중성,종성을  분석해서  벌수를
       알아 내는 루틴을 만들어 보죠.

         역시 테이블처리를 하면 간단합니다.

         unsigned char cho[]={
              0, 0,0,0,0,0,0,0,0,1,3,3,3,1,2,4,4,4,2,1,3,0
              };
         unsigned char cho2[]={
              0, 6,6,6,6,6,6,6,6,7,8,8,8,7,7,8,8,8,7,7,8,6
              };
         unsigned char jong[]={
              0, 0,2,0,2,1,2,1,2,3,0,2,1,3,3,1,2,1,3,3,1,1
              };

         void puthan(unsigned code)
         {
           char bul1,bul2,bul3; /* 초성,중성,종성 벌 저장변수 */
           …

           if(last==0) { /* 먼저 종성이 있는 지 없는 지를 조사 */
                  bul1=cho[middle];                   /* 초성 */
                  if(first==1||first==24) bul2=1;     /* 종성 */
                  else bul2=2;
                  … /* 이부분에서 합성하고 출력하도록하죠. */
                  }
           else {
                  bul1=cho2[middle];                  /* 초성 */
                  if(first==1||first==24) bul2=3;     /* 종성 */
                  else bul2=4;
                  bul3=jong[middle];
                  …
                }
         }

         바로 이렇게 bul1,bul2,bul3 형태로 나누는 검니다. 초성의 경우
       중성문자에 따라 벌수를 정하고 중성은 ‘ㄱㅋ’인지를 조사해서  벌
       수를 정하고 종성은 중성에 따라 역시 정하면 되지요.

         이렇게 벌수를 나누었는 데… 실제로 벌수는 어떻게 쓰일 까요?
       바로 폰트를 읽어들인 버퍼에서 해당 글자의 위치를 벌수에 맞추어
       이동시켜주면 됨니다.

         간단히 어드레스 계산에 대해 알아보죠.

         각 글자 모양은 32바이트로 이루어져 있습니다.(가로 16,세로 16
       인데 가로의 경우 2바이트가 16비트이므로 2*16바이트에  폰트모양
       을 나타내는 거죠.) 그러니 초성이나 중성이나  각  글자별 코드에
       32를 곱하면 해당 글자모양의 위치를 알수있습니다.

         벌수의 경우에는 글자 하나를 뛰어 넘는 것이 아니라  아예 몽땅
       뛰어 넘는 것이므로 각 묶음의 크기를 알아야 합니다. 초성의 경우
       20자(빈공간포함 초성19자)이니 20*32하면 한 벌의 크기를 알수있
       죠.(640이죠?) 앞에서 글자크기에 글자코드를 곱해서 위치를  얻은
       것과 마찬가지로 벌수크기에 벌수를 곱하면 각 글자의 벌수를 알수
       있지요.

         초성 20자*32=640
         중성 22자*32=704
         종성 28자*32=896

       참고) 전체크기 640*8+704*4+896*4=5120+2816+3584=11520

         초성,중성,종성 글자의 포인터 위치를 알아내는 식을 아래와 같
       이 나타낼수있죠.

         위치 = 벌크기 * 벌수 + 글자크기 * 글자번호

       5. 문자 합성

         이제 모든 준비가 되었군요.이정도면 출력 루틴을 만드실수 있겠
       겠죠?

         한글코드를 주면 문자를 합성해서 리턴해주는 함수를 만들어  보
       겠습니다.여기에 위에서 쓴 대부분의 내용이 나오겠죠.

         아래가 바로 구현 소스임니다.

       unsigned char *font; /* 여기에 폰트데이타 11520byte가 있죠. */

       unsigned char _first[]={0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
       17,18,19 };
       unsigned char _middle[]={ 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 };
       unsigned char _last[]={ 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 };
       unsigned char cho[]={0,0,0,0,0,0,0,0,0,1,3,3,3,1,2,4,4,4,2,1,3,0 };
       unsigned char cho2[]={0,6,6,6,6,6,6,6,6,7,8,8,8,7,7,8,8,8,7,7,8,6};
       unsigned char jong[]={0,0,2,0,2,1,2,1,2,3,0,2,1,3,3,1,2,1,3,3,1,1};

       #define COPY(A,B) for(loop=0;loop<32;loop++) *(B+loop)=*(A+loop);
       #define OR(A,B) for(loop=0;loop<32;loop++) *(B+loop)|=*(A+loop);

       void hancode(unsigned code,unsigned char *buffer)
       {
         unsigned first,middle,last,loop;
         unsigned offset;

         first=_first[(code>>10)&31];
         middle=_middle[(code>>5)&31];
         last=_last[(code)&31];

         if(last==0) {
                offset=cho[middle]*640;                    /* 초성 */
                offset+=first*32;
                COPY(font+offset,buffer);
                if(first==1||first==24) offset=5120;       /* 중성 */
                else offset=5120+704;
                offset+=middle*32;
                OR(font+offset,buffer);
                }
         else {
                offset=cho2[middle]*640;                   /* 초성 */
                offset+=first*32;
                COPY(font+offset,buffer);
                if(first==1||first==24) offset=5120+704*2; /* 중성 */
                else offset=5120+704*3;
                offset+=middle*32;
                OR(font+offset,buffer);
                offset=5120+2816+jong[middle]*896;         /* 종성 */
                offset+=last*32;
                OR(font+offset,buffer);
              }
       }

       6. 영문자합성

         영문자는  폰트에 따라 다르지만 폰트가 아스키코드 그대로 있다
       고 한다면 아래와 같이 위의 한글 형태로 작성할수있습니다.
         (영문자는 8×16으로 한글자가 16 byte로 이루어져 있습니다.)

       unsigned char *fonte; /* 영문 폰트 (16*256)byte */

       void engcode(unsigned char code,unsigned char *buffer)
       {
         unsigned offset,loop;
         offset=code*16;
         COPY(fonte+offset,buffer);
       }

       7. 문자 출력

         이제 문자 합성도 되니 출력하는 일만 남았군요.먼저 bit이미지를
       출력하는 루틴을 만들어야 겠네요.특정모드용은 각자 만드시길 바라
       고 간단히 점찍는 함수를 이용해서 비트이미지 출력하는 루틴을  만
       들어보죠.

       unsigned char bitmask[]={128,64,32,16,8,4,2,1};

       void _8x16(int x,int y,unsigned char color,char *image)
       {
         unsigned char xs,ys;
         for(ys=0;ys<16;ys++) for(xs=0;xs<8;xs++)
              if(image[ys]&bitmask[xs]) pixel(x+xs,y+ys,color);
       }

       void _16x16(int x,int y,unsigned char color,char *image)
       {
         unsigned char xs,ys;
         for(ys=0;ys<16;ys++) {
              for(xs=0;xs<8;xs++)
                   if(image[ys*2]&bitmask[xs]) pixel(x+xs,y+ys,color);
              for(xs=0;xs<8;xs++)
                   if(image[ys*2+1]&bitmask[xs]) pixel(x+xs+8,y+ys,color);
              }
       }

       8. 글출력

         대충 함수들이 다 모였군요.간단히 위의 함수들로 문장출력하는루
       틴을 또 만들어보죠.

       void string(int x,int y,unsigned char color,unsigned char *str)
       {
          unsigned code;
          unsigned char temp[32];
          while(*str){
               code=*str++;
               if(code>=128) { /* 한글 */
                   code*=256;
                   code|=*str++;
                   hancode(code,temp);
                   _16x16(x,y,color,temp);
                   x+=16;
                   }
               else {
                   engcode(code,temp);
                   _8x16(x,y,color,temp);
                   x+=8;
                   }
               }
       }

       /* 예. string(10,10,2,”우하하..푸하하…PUHAHA”); */

       9. 끝

         간단히 문자 출력하는 루틴에 대해 썼는 데… 왜 쓴건지에 생각
       하면서 마침니다.( 왜 쓴거지? 시간이 남아도나? ) – 헛소리해서
       죄송합니다.

      ————————–
       *** 출력종료 ***

      —————————————————————–
      이상은 약간 아카데믹한 소스였으나 그런대로 쓸만한 것입니다만 …
      좀더 프로폐쇼날해봅시다.. 한바이트를 아끼기 위해서 날밤 새는 것도
      아끼지 않는 프로가 이정도 소스로 만족할 수 있나요?
      —————————————————————–
       하기 소스는 필자가 ROHM사의 써멀 프린터 인터페이스를 만들기 직전에
       베타버전으로 ICCZ80 과 사용법이 유사한 볼랜드C++ 3.1 (DOS) 를 이용해
       서 비트버퍼에 제대로 폰트가 로딩되는지를 테스트한 소스이다.

       allfont.bin 이란 파일은 각종 폰트들을 와장창 묶어서 alllfont.s01로
       만든 것을 인텔헥사 파일로 만들고 헥사빈 유틸리티로 만든 것이다.

       다음의 배치파일이면 간단하게 만들 수 있다.
       이것은 별도의 xcl 화일이 필요없다.
       @echo off
       @echo    XXX-XXXX FONT BIN Maker Ver 1.0
       @echo    (c) Copyright by XXXX Co., Ltd.
       @del   %1.r01
       @az80  %1,%1,%1,
       @if errorlevel 1 goto end
       @del   %1.hex
       @del   %1.bin
       @xlink -cz80 %1 -o %1.hex
       @if errorlevel 1 goto end
       @hexbin %1.hex %1.bin
       @del    %1.r01
       @del    %1.hex
       :end
       하기 소스는 베타테스트용 소스로써 ICCZ80으로 포팅직전에 테스트한
       소스이므로 버그가 있을 수 있다는 점을 확실히 밝힌다. 각자의 하드
       웨어 맞도록 수정하면 될 것이다.

       약간 과격한 발언을 잠깐 하겠다.
       —————————————————————–

       하기 소스는 조합형 한글/영문/특수문자/확대문자/그림문자 프린터의
       모체가 되는 바이오스 부분이다. 상업적으로는 얼마든지 카피가능하나
       학술적으로 자신의 책에 인용한다거나 등으로 마치 자기가 풀로 다짠
       소스인것처럼 인용시 필히 디동에서 매장됨을 명심할것

       ( 무슨 얘기가 그래? )
       ( 그런 책들을 쓴 인간들을 많이 봤걸랑.. )

       —————————————————————–

       소스에 대한 해설은 별도로 하지 않겠다.

       ( 알아서 분석하란 뜻 )
       ( 이정도 상업적인 소스를 공개하는 것도 어딘데 해설까지 해줘? )
       —————————————————————–
      #include “stdio.h”
      #include “stdlib.h”
      #include “string.h”
      #include “conio.h”
      #include “io.h”

      /*
         #############################################################
         ##                                                         ##
         ##  다음 프로그램은 XXX-XXXX 써멀 프린터 구동 알고리듬을   ##
         ##  소프트웨어적으로 C언어를 사용해 에뮬레이트 한 것으로   ##
         ##  ICCZ80 측에 포팅시키기전에 인자 알고리듬검증 및 디버   ##
         ##  깅을 사전에 행하기 위해서 구현된 프로그램이다.         ##
         ##  하기 폰트 로딩 및 한글.영문 혼용 프린트루틴의 구현은   ##
         ##  하늘소의 한글라이브러리에서 그 원천 기술을 아웃소싱    ##
         ##  했으며 폰트 로딩기법은 독자적으로 구현한 것이다.       ##
         ##  또한, 폰트의 가로.세로 확대 프로그래밍기법은 오리지날  ##
         ##  XXX-XXXX의 소스와 독자적인 연구에 의해서 구현했다.     ##
         ##                                                         ##
         ##  하기 알고리듬은 외부 공개를 일체 금지하며 프린트되는   ##
         ##  비트 결과는 EMUPRT > ???.TXT 같은 명령으로 쉽게 확인   ##
         ##  해 볼 수가 있을 것이다.                                ##
         ##                                                         ##
         ##  ICCZ80으로 포팅시 라벨뒤의 ‘;’ 문자를 제거해야 한다.   ##
         ##                                                         ##
         ##                                                         ##
         ##  제작자   : XXXXXX시스템, XXXX 손민철                   ##
         ##  폰트제작 : XXXXXX시스템, XXXX 손민철 ( ALLFONT.BIN )   ##
         ##  제작일   : 1999년 8월 30일 ~                           ##
         ##  제작언어 : 볼랜드C++ 3.1 도스버전                      ##
         ##                                                         ##
         ##                                                         ##
         #############################################################

         개정내용 :

          99년 9월 3일(금) : 에뮬레이트 일차 성공

             -  32 X 32 사이즈 문자와 32 X 32 사이즈 미만
                의 문자와 혼용시 버그

             -  라인을 강제로 빠르게 이동시키는 방안을 모색해야 함
                ( 모터를 공회전시킬 것인가, 널을 인자할 것인가 선택 )
                ( 일단, 실제 인자 성공후에 고려해보기로 함 )

      */
      /* ###############################
         ##  인자시 필요한 전역변수   ##
         ############################### */

      unsigned char FONTDATA[18000];
      unsigned char _P_TEXT[40][60];
      unsigned char _BUFFER[128];
      unsigned char _TEMP_BUFFER[128];
      unsigned char _prt_bit_buffer[1728];
      int           _REVERSE;
      int           _ENLARGE;
      int           _UNDERLINE;
      int           _P_LINE;
      int           _P_COL;
      int           _S_COL;
      int           _P_COUNT;
      /* 초성 인덱스 테이블 */
      const unsigned char idxtbl1[] = {
            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};
      /* 중성 인덱스 테이블 */
      const unsigned char idxtbl2[] = {
            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};
      /* 종성 인덱스 테이블 */
      const unsigned char idxtbl3[] = {
            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};
      /* 중성에 따른 초성의 종류 / 받침 없음 */
      const unsigned char type1tbl_no[]  = {
            0,0,0,0,0,0,0,0,0,1,3,3,3,1,
            2,4,4,4,2,1,3,0};
      /* 중성에 따른 초성의 종류 / 받침 있음 */
      const unsigned char type1tbl_yes[] = {
            5,5,5,5,5,5,5,5,5,6,7,7,7,6,
            6,7,7,7,6,6,7,5};
      /* 중성에 따른 종성의 종류 */
      const unsigned char type3tbl[] = {
            0,0,2,0,2,1,2,1,2,3,0,2,1,3,
            3,1,2,1,3,3,1,1};
      /* 함수 프로토타잎 ( Borland C ONLY definition )   */

      void load_font_data();
      void _init_prt(),_send_one_line(int),clrbuff();
      void Get_KP_font(unsigned int);
      void Get_EP_font(unsigned char),Get_MP_font(int);
      void execute_print();
      void low_level_prt(unsigned char);
      void line_print(unsigned char *);
      void _init_prt(void)
      {
           int i;
           memset(_BUFFER,0×00,128);
           memset(_TEMP_BUFFER,0×00,128);
           memset(_prt_bit_buffer,0×00,1728);
           _P_LINE=0;
           _P_COL=0;
           _S_COL=0;
           _P_COUNT=0;
           _REVERSE=0;
           _UNDERLINE=0;
           _ENLARGE=0;
           for(i=0;i<40;i++) memset(_P_TEXT[i],0×00,60);
           memset(_P_TEXT[40],0×00,60);
      }

      void load_font_data(void)
      {
        FILE *f;     /*  폰트화일을 통체로 한 스트링으로 읽어들임   */
        int i=0,j=0;
        f=fopen(“allfont.bin”,”rb”);
        YY:;
        i=getc(f);
        if(i != EOF){
          FONTDATA[j++]=i;
          goto YY;
        }
        fclose(f);
      }

      void _send_one_line(int line)
      {
        int a,b;
&n

댓글 0

조회수 580

등록된 댓글이 없습니다.

C언어HOME > C언어 > 전체 목록

게시물 검색

2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2017
모바일버전으로보기