Previous Next Table of Contents

6. X 프로그래밍 기초 : 한글폰트

자, 복습해볼까요? X 윈도우에서 하나의 문자 또는 문자열을 출력하기 위해서는 몇 가지 과정을 거쳐야 합니다.

  1. 자신이 원하는 폰트명( XLFD 방식이든 별명이든 간에... )을 알고 XLoadFont 함수로 X 윈도우의 폰트서버(xfs)로부터 Font ID를 받아옵니다.
  2. 그 ID 를 가지고 그래픽 콘텍스트(GC)에 등록합니다.
  3. 이제 마지막으로 XDrawString 함수를 써서 원하는 창의 원하는 위치에다 문자열을 뿌려줍니다.

아주 간단한 과정이죠? 오늘은 이것을 심화학습하겠습니다. 그리고 한글 출력에 대하여 알아보도록 하죠.

6.1 한글 출력에 관한 몇 가지 이야기

시작하는 지루한 이야기

컴퓨터를 쓰면서 우리를 가장 많이 괴롭히는 문제 중에 하나가 바로 한글 문제 입니다. 잘못된 정치로 인해 우리 한글 코드는 조합형/완성형 이제는 얼마전 공진청에서 만든 거의 유명무실한 KSC5700 코드, M$ 등이 주축이 되어 추진하고 있는 유니코드, M$ 사에서 한국인들을 우롱하는 듯이 버젓이 만들어 놓고 윈도그 95와 윈도그 NT 에서 쓰고 있는 확장완성형( 또는 통합완성형, 이름이 어찌 되었든 실체는 같음 )이 있습니다. 우리의 한글이 거의 몸살을 앓고 있다고 해도 과언이 아닙니다. 컴퓨터의 초창기( 현재의 한컴사 사장 이찬진씨가 그 유명한 아래한글을 만들던 시절 이전 )에 각 회사에서 왕성하게 보여주었던 한글화의 열기는 정말로 뜨거웠습니다. 그야 물론 당연히 조합형이었지요. 하지만 정부와 몇몇 관변 정부의 하수인 관변 학자들 덕분에 완성형이라는 괴물이 탄생하였고, 그 이후 한글화의 열기는 찬물을 뒤집어 썼습니다. 게다가 한글은 어느새 기업이 소프트웨어를 팔아먹기 위한 무기가 되어버리고 말았습니다. 한글화 기술은 기업의 독점적인 라이센스나 다름 없어졌고 M$ 사의 경우에는 더더욱 한글을 볼모로 삼고 있지요.

리눅서들에게 한글화 기술을 가져다 줄 회사는 없습니다! 바로 우리들의 힘으로 이룩해야 합니다. 또한 리눅서들은 남들이 해주길 바라지도 않습니다. 바로 이제부터 우리 스스로의 힘으로 아름다운 한글을 구현해 나갑시다. 한글을 볼모로 잡고 소비자를 우롱하는 기업들에게 본때를 보여줘야 할 시간이라고 생각합니다.

한글 출력! 무엇이 다른가?

모든 문제는 바로 영문 로마자는 1 바이트로 표현하고도 남는 반면, 한국어, 중국어 일본어와 같은 동양권 언어들은 2 바이트 이상을 필요로 한다는 것입니다. 따라서 1 바이트 로마자를 출력하는 함수와는 다른 방식의 함수를 사용하며, 문자열에 대한 약간의 가공과정을 거쳐야 합니다.

그 외에 폰트를 읽어오는 것, GC에 등록하는 것과 같은 과정은 차이 없습니다. 단지 조건이 하나 있다면 X 폰트서버(xfs, X 윈도우를 시작하면 우리 모르게 떠 있습니다 그러니 걱정하실 필요없음 )가 2 바이트 출력을 지원하느냐의 문제인데, 요즘에 2 바 이트 지원하지 않는 X 서버도 있나요? :)

X 윈도우에서 한글 어플을 개발하는 방법

X 윈도우에서 한글 어플리케이션을 개발하는 방법은 크게 2 가지가 있습니다.

이외에도 우리가 윈도그에서 주로 사용하였던 한메한글처럼 HanX 라고 하는 것을 이용해서 한글을 볼 수 있도록(출력만) 하는 방식도 있습니다.

우리가 익혀야 할 것은 전자/후자의 개발 모두에 공통되는 가장 기본적인 한글출력 방법입니다. 현재 저는 후자의 개발에 노력 중입니다. 어서 빨리 XFree86 에도 상용 못지 않은 한글 시스템을 탑재하여 프로그램 개발에서 한글 처리에 할애하는 시간과 노력을 아낄 수 있도록 해야한다고 믿습니다.

6.2 한글 출력 과정

무엇이 또 문제인가?

현재 X 윈도우에서 사용되는 한글 폰트의 종류는 크게 3 가지라고 말할 수 있습니다. 1 번째로는 여러분이 애용하시는 한텀 조합형 폰트입니다. 2 번째는 대우폰트, 한양폰트 등의 완성형 폰트입니다. 3 번째는 같은 완성형 폰트이면서도 앞의 두 개와는 아주 사소하게 다른 처리과정을 거쳐야 하는 삼보 폰트가 있습니다.

이렇게 다양한 폰트 형식의 존재는 다양한 폰트 출력 예비작업이 필요함을 의미 합니다.

저는 일단 여기서 제일 간단한 2 번째 경우만 설명드리기로 하겠습니다. 미려한 폰트인 1 번째 한텀 조합형 폰트의 출력을 다른 한 번의 강의를 할애해야 할 만큼 많은 이야기가 필요하기 때문입니다. ( 사실은 삼보 폰트가 더 쉽지만서도 구할 수가 없으니... )

자, 그러면 여러분이 완성형 방식의 폰트를 가지고 있다고 생각하고 시작하겠습니다

 함수의 원형 : <X11/Xlib.h> 에 선언

  XDrawString16(display, d, gc, x, y, string, length)
             Display *display;
             Drawable d;
             GC gc;
             int x, y;
             XChar2b *string;
             int length;

우리는 한글 폰트를 가지고 한글을 출력하기 위해서 XDrawString 이라는 1 바이트 언어권 함수를 사용하지 않고 끝에 16이라는 숫자가 붙은 함수를 사용하게 됩니다. 그리고 유심히 살펴보면 XDrawString 에서는 char * 형이었던 부분이 여기서는 XChar2b * 형으로 바뀌어 있죠. 우리는 여기서 새로운 자료형에 대해서 또한 알아봐야 합니다. :<

  typedef struct {         /* normal 16 bit characters are two bytes */
            unsigned char byte1;
            unsigned char byte2;
   } XChar2b;

우리 말에 대한 표현은 현재 2 바이트 표현법이 가장 많이 사용되고 있으면 표준적이라고도 말할 수 있을 것 같습니다. 한글 한 글자 "한" 이라는 문자는 영문 2 바이트로 되어 있고 그것과 일대일 대응하는 것이 바로 XChar2b 형 변수입니다. 따라서 우리는 char * 형 배열을 XChar2b * 형 배열로 변환시켜 주기만 하면 됩니다. 근데 우리가 많이 가지고 있는 한양폰트나 대우폰트의 경우, 말이 쉽지 그렇게는 되진 않습니다.

다음과 같은 연산이 이루어져야 합니다. 일단 '한'이라고 하는 2 바이트 한글 한 글자가 있다고 치면...

   char *Han = "한";
   XChar2b HanX;

   HanX.byte1 = *(Han)   - 0x80;        /* 주의! 0x80 값을 빼주고 있다 */
   HanX.byte2 = *(Han+1) - 0x80;

보시다시피 그냥 한글 2 바이트와 XChar2b 형 구조체 멤버 간의 간단한 일대일 대응이 아니라, 0x80 값을 빼주어야 한다는 자잘한 중간 과정이 필요합니다. ( 참고로 삼보 폰트는 0x80 값은 값을 빼주지 않고 그냥 일대일 대응시킵니다. )

이제 좀 감이 오셨습니까? 알고 나니 굉장히 쉽지 않나요? :)

#include <X11/Xlib.h>
#include <stdio.h>

int main()
{
        Display *dpy;
        int screen;
        Window w;
        Font hanFont, engFont;
        GC gc;
        XChar2b HStrBuf[256];
        int n;

        dpy = XOpenDisplay( NULL );

        screen = DefaultScreen( dpy );
        w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 400, 300, 2, 
                        BlackPixel( dpy, screen ), WhitePixel( dpy, screen ));
        XMapWindow( dpy, w );
        XFlush(dpy);

        sleep(4);       /* 왜 넣었을까요? */

        gc = XCreateGC ( dpy, w, 0L, (XGCValues *) NULL );
        hanFont = XLoadFont ( dpy, 
                        "-daewoo-mincho-*-r-normal--16-*-*-*-c-*-*-*" );

        engFont = XLoadFont ( dpy, "fixed" );

        XSetFont( dpy, gc, hanFont );
        n = convert_ks_to_display("안녕하세요리눅서", HStrBuf, 10);
        XDrawString16(dpy, w, gc, 100, 100, HStrBuf, n);

        XSetFont( dpy, gc, engFont );
        XDrawString(dpy, w, gc, 100, 150, "Welcome to Linux!", 17 );

        XFlush(dpy);
        getchar();
}

/* 한텀 소스에서 인용 */

int convert_ks_to_display(char *str, XChar2b *buf, int n)
{
  int i, j;

  for (i = 0, j = 0; i < n;) {
    buf[j].byte1 = str[i] - 0x80;
    buf[j].byte2 = str[i+1] - 0x80;
    i += 2, j++;
  }
  return j;
}

컴파일 방법은 똑같습니다. 이상 없이 실행되려면 여러분은 /usr/X11R6/lib/fonts 디렉토리의 하부 디렉토리 misc 디렉토리에 대우 폰트가 설치되어 있어야 합니다. 화일명은 hanglm16.pcf.Z 입니다. fonts.dir 화일을 살펴보시기 바랍니다. 현재 가지고 계시는 완성형 방식의 폰트를 아무거나 적어주시면 됩니다. 전에 설명드렸던 XLFD 방식의 표기 또는 자주 쓰는 폰트명에 대하여 fonts.alias 에다 별명을 정해주시고 그 별명을 사용하시든지 마음대로 하시면 됩니다. 참고로 위에서 사용한 영문 폰트명 fixed 는 사실 별명에 해당됩니다. fonts.alias 맨 앞에 정의되어 있습니다.

아직도 남은 문제가 있다!

한글로 출력을 해보시니 어떠세요? 제가 처음으로 한텀 소스를 보고 독학하면서 별것 아니지만서도 한글이 출력되니 참 기분이 좋더군요. 근데 문제는 그렇게 간단하지 않았습니다. 무엇이냐구요?

위의 소스를 잘 살펴보시기 바랍니다. 잘 보시면 한글은 한글대로 따로, 영문은 영문대로 따로 출력하고 있습니다. 이것이 무엇을 의미하는 것일까요? 예! 그렇습니다. 우리는 안타깝게도 한글과 영문을 혼용해서 쓰는 시대에 살고 있습니다. 따라서 우리는 종종 사용자로부터 다음과 같은 문자열을 받게 됩니다.

 char *MixedString = "저의 코넷 주소는 freeyong@soback.kornet.nm.kr 입니다";

무엇이 문제이겠습니까?

XDrawString 함수는 오로지 1 바이트 문자권 폰트만 출력합니다. 이에 비하여 XDrawString16 함수는 반대로 2 바이트 문자권 폰트만 출력합니다. 그렇다면 위와 같이 한글과 영문이 섞여 있는 경우에는 문자열을 주욱 검색하면서 한글과 영문을 따로 출력해주어야 한다는 결론이 나옵니다. :<

이 부분이 약간의 노력을 필요로 한다고 할 수 있습니다. 영문과 한글의 조화를 맞추는 것이 현재로서는 아주 중요합니다. 어찌 하다보니 우리나라도 영어문화권이 되버린 듯한 씁쓸한 기분을 버릴 수가 없네요. 특히 컴퓨터 분야에 있어서 한글만 잘되고 영문은 대신에 꽝이 되버린다면 아무도 그거 쓰지 않습니다.

따라서 여러분은 폰트 로딩/폰트를 GC 에 등록/폰트 출력 이렇게 간단한 과정을 넘 어서서 폰트에 대해여 자유자재로 처리하실 수 있는 능력이 필요하게 됩니다.

한글과 영문을 구별해서 찍기

여기서부터는 좀 어려워지기 시작합니다. 제가 여기에 적어놓은 함수는 한텀 소스에서 한글처리 부분을 보고 고대로 저의 한글 fvwm 2.0.42의 한글 처리루틴으로 복사하고 약간을 수정한 것입니다. 이 모든 부분을 이해하실 필요는 없습니다. 그리고 어느 정도 실력이 되시는 분들은 이미 다 알고 계시는 내용이라고 믿습니다. 여러분이 주목하셔야 할 부분은 소스 안에서 설명을 드리겠습니다.

void HanXDrawString(Display *d, Drawable w, GC gc, XFontStruct *hfont,
        XFontStruct *efont, int x, int hy, int ey,
        char *str, int len, int hcode, int ftype )
{
  int n;
  char *p;
  XChar2b buf[256];

/*

  이 함수는 보통의 아스키 영문자와 한글이 혼합되어 있는 문자열을 받습니다. 
  여기서는 str 이라는 변수입니다.
  
*/ 

  while (len > 0) {
    if (*str & 0x80) {
    /*
        바로 0x80 과 AND 연산을 함으로써 바이트의 8 번째 비트가 1 로 되어 있는
        가를 확인합니다. 그래서 참이면 그 바이트와 다음 바이트 두 개는 한글을
        구성한다고 할 수 있습니다. 
    */
    
      for (p = str; len > 0 && (*p & 0x80); p += 2, len -= 2)
        ;

    /*    
       여기에 for ( ) ; 라고 하는 재미있는 문장이 있습니다. 현재 한글이 처음으
       로 나타난 위치부터 어디까지 한글이 지속되는가를 체크해서 한글 문자열만
       추려내어 처리하고자 하는 겁니다.
    */

      n = HanXCharConvert(str,buf,p-str, hcode, ftype );
      XSetFont( d, gc, hfont->fid );
      XDrawString16(d,w,gc,x,hy,buf,n);
      /* 바로 여기서 XDrawString16 함수를 써서 출력하고 있습니다 */
      x += XTextWidth16(hfont,buf,n);
      /* XTextWidth16 이라는 함수는 눈여겨 보셔야겠죠? */
    }
    else {
    /* 영문일 때 처리하는 루틴입니다 */
      for (p = str; len > 0 && !(*p & 0x80); p++, len--)
        ;
      /* 마찬가지로 계속적으로 ASCII 문자만 나올 때까지 포인터 이동 */
      XSetFont( d, gc, efont->fid );
      XDrawString(d,w,gc,x,ey,str,p-str);
      x += XTextWidth(efont,str,p-str);
    }
    str = p;
  }
  XSetFont( d, gc, efont->fid );
}

/*
   위에서 쓸 데 없이 계속 XSetFont 를 쓰는 이유는 하나의 GC 에다가 한 번은
   한글 폰트를 등록했다가, 또 한 번은 영문 폰트를 등록하는 작업을 하기 때문
   입니다.
*/

자, 설명을 드리죠. 위에서 사용한 테크닉은 한글 프로그래밍을 하시려는 분들은 아주 기본적으로 익히셨어야 하는 내용입니다. 한글 한 글자는 2 바이트이며, 첫번째 바이트의 MSB 는 1 로 셋팅된다는 사실이죠. 그래서 한글인지 아닌지를 체크하는 가장 기본적이면서도 유일한 방법은 바로 비트매스크 연산을 해보는 겁니다. 0x80 이니깐 이진수로는 1000 0000 입니다. 이 숫자와 & 연산을 하면 둘 다 1 인 경우만 참이 되므로 과연 MSB 가 1 인가 아닌가를 식별해낼 수 있는 것입니다.

자세한 내용은 C 언어책을 보시고 비트매스크 연산을 공부하시기 바랍니다. 제가 권하고 싶은 책은 커니건 & 리치의 "C Programming Language" 입니다. 커니건과 리치가 어떤 사람인지는 아시죠? :) 모르시면 꼭 알아보세요. 기초 상식에 해당하니깐요 :)

폰트에 대한 중요한 정보 알아내기

한글 출력 벌써부터 이렇게 어렵군요. ( 근데 한글 입력은 더욱 더 황당할 겁니다 )

이제부터 다루고자 하는 내용은 우리가 처할 수 있는 어떤 경우에라도 자유자재로 폰트를 처리하는 방법에 대한 것입니다. XDrawString 이나 XDrawString16 이라는 함수는 우리가 정해주지 않아도 폰트 고유의 특성에 따라 문자열을 예쁘게 한 줄로 나타내줍니다. 하지만 두 줄 이상이 되는 문자열은? 줄간격을 어떻게 할까요? 출력된 문자열은 도대체 얼마의 폭을 가지고 있는지... 등등 문자열을 여러분 마음껏 출력하기 위해서는 폰트에 대한 전반적인 정보 또는 필요에 따라 한 글자 한 글자에 대한 정보를 알아내야 합니다.

근데 폰트에 대한 정보는 어디에 있다고 했죠? 예. 맞습니다. 그것은 X 서버에 있습니다. 우리는 보통 가장 간단한 형태로서 XLoadFont 함수를 써서 폰트 ID 를 얻어옵니다.

가장 간단한 방법

       XQueryTextExtents16(display, font_ID, string, nchars,
       direction_return, font_ascent_return,
                               font_descent_return, overall_return)
             Display *display;
             XID font_ID;
             XChar2b *string;
             int nchars;
             int *direction_return;
             int *font_ascent_return, *font_descent_return;
             XCharStruct *overall_return;

우리가 사용하고자 하는 함수는 바로 XQueryTextExtents16 이라는 아주 긴 이름을 가진 함수입니다. 우리 비영어 문화권 사람들에게는 힘들지 몰라도 그들에게는 쉬운 함수명이겠죠? X 로 시작하는 함수는 바로 Xlib 함수임을 의미하는 것이고 Query 조사하다, TextExtents 는 텍스트의 영역 범위, 뒤에 16 을 붙인 것은 1 바이트권 문자가 아니라 2 바이트권 문자임을 나타내주고 있습니다. 일단 위에서 폰트 ID 변수형이 XID 인 것은 여러분이 생각해 보십시요. 2 바이트권 문자열이므로 XChar2b 형 배열을 사용하였고 nchars 는 그 배열의 크기를 알려줍니다 이제부터 4 개의 포인터 전달변수들이 있군요. 여러분이 생각하기에 왜 이 녀석들은 포인터로 주어졌을까요? 맞습니다. 이 변수들에다가 우리가 원하는 정보를 얻어 오려고 하는 것입니다.

direction_return 은 FontLeftToRight, FontRightToLeft 라는 정보가 들어 있습니다 영어를 좀만 읽으실 수 있다면 무슨 뜻인지 아실 겁니다. 보통의 경우 FontLeftToRight 이겠죠? 문자열의 출력이 좌 --< 우 인가? 아니면 그 반대인가 입니다.

font_ascent_return과 font_descent_return 에 대한 이야기는 한글 문자와는 다른 영문 문자만의 특성에 대해서 알아야 얘기가 될 것 같군요. 우리 문자는 이러한 개념이 없다고나 할까요? 영문자 y 를 예로 들어봅시다. 보통 우리가 중학교 처음 들어가서( 윽! 요즘은 초등학교에서부터 하나요? ) 영어 시간에 하는 일은 알파벳 쓰기였습니다. 일단 문방구에 가서 따로 제작된 영어 노트를 한 권 삽니다. 공책을 펼치면 마치 오선지처럼 줄이 주욱주욱 그어져 있고, 자세히 보시면 파란줄 말고 빨간줄이 그어져 있던 것이 기억나십니까? 그 빨간줄은 baseline 이라고 합니다. a b c 와 같은 문자는 모두 그 빨간줄 위에 씌여집니다. 하지만 g j y 같은 문자들은 빨간줄 아래로 내려가는 부분이 있지요? 이제 감이 오셨을 겁니다. font_ascent_return ( ascent의 의미와 descent의 의미를 사전을 찾아보시면 아주 명확해집니다 )는 그 빨간 baseline 위로 몇 픽셀만큼 올라가 있는가? 그리고 font_descent_return은 baseline 아래로 얼마만큼인가를 나타내줍니다. 우리 한글과는 전혀 관련이 없다고 할 수 있죠. :) 하지만! 그렇지도 않습니다. 우리가 한글과 영문을 혼용할 때 우리 한글은 영문과 조화를 이루기 위해서 항상 baseline 위에 씌여져야 하겠죠? 엉뚱하게 y 자의 밑부분과 평행하게 씌여지면 영 보기 싫어집니다.

overall_return은 글자 그대로 전반적인 정보를 가져다 줍니다. 새로운 자료형이군요. XCharStruct 라는.... 이 자료형이 어떻게 이루어져 있는지는 Xlib.h 헤더 화일에서 찾아보면 다음과 같습니다.

/*
 * per character font metric information.
 */
typedef struct {
    short       lbearing;       /* origin to left edge of raster */
    short       rbearing;       /* origin to right edge of raster */
    short       width;          /* advance to next char's origin */
    short       ascent;         /* baseline to top edge of raster */
    short       descent;        /* baseline to bottom edge of raster */
    unsigned short attributes;  /* per char flags (not predefined) */
} XCharStruct;

이 함수를 사용하는 이유는 과연 지금 출력하려고 하는 문자열이 어느 만큼의 영역을 차지할 것인가를 가늠하는 것입니다. 문자열의 높이(height)는 다음과 같습니다.

        ascent 멈버 + descent 멤버

위로 얼마만큼이며, 아래로 얼마만큼인지를 더하면 됩니다. 한글은 descent = 0 :) 그래도 일관성을 위해서 항상 이렇게 써주십시요.

다음으로 문자열의 폭(width)은 어떻게 계산할까요?

        rbearing 멤버 - lbearing 멤버   또는 그냥 width 멤버를 사용

1 바이트권 문자에 대해서는 XQueryTextExtents 를 씁니다.

더 좋은 방법

위의 방법은 어떤 정보를 알고자 할 때 항상 X 서버에게 요청을 해야 하므로 네트워크 로드가 많이 거리게 되며, 프로그램이 느려지는 주범이 됩니다. 그래서 프로그램다운 프로그램을 짜는 경우에는 대부분 XLoadFont 로 폰트로딩하고, XQueryTextExtents(16) 같은 함수를 사용하지 않고 다른 방법을 사용합니다.

XLoadFont 대신에 XLoadQuerFont 함수를 씁시다.

XLoadQueryFont 는 폰트를 로딩하면서 Query 한다는 의미입니다.

        XFontStruct *XLoadQueryFont(display, name)
                     Display *display;
                     char *name;

XLoadFont에서처럼 폰트명을 전달해주는 것은 같지만, 보시는 바와 같이 반환되는 값이 Font 형이 아니라 XFontStruct 라는 자료형입니다.

typedef struct   
  XExtData    *ext_data;      /* hook for extension to hang data */
  Font        fid;            /* Font id for this font */ /* 주목! */
  unsigned    direction;      /* hint about direction the font is painted */
  unsigned    min_char_or_byte2;/* first character */
  unsigned    max_char_or_byte2;/* last character */
  unsigned    min_byte1;      /* first row that exists */
  unsigned    max_byte1;      /* last row that exists */
  Bool        all_chars_exist;/* flag if all characters have non-zero size*/
  unsigned    default_char;   /* char to print for undefined character */
  int         n_properties;   /* how many properties there are */
  XFontProp   *properties;    /* pointer to array of additional properties*/
  XCharStruct min_bounds;     /* minimum bounds over all existing char*/
  XCharStruct max_bounds;     /* maximum bounds over all existing char*/
  XCharStruct *per_char;      /* first_char to last_char information */
  int         ascent;         /* log. extent above baseline for spacing */
  int         descent;        /* log. descent below baseline for spacing */
} XFontStruct;

자료형이 꽤 복잡한 편에 속하는군요. :) 주목하실 것은 폰트 ID 가 XFontStruct 자료형의 fid 멤버에 저장되어 있다는 사실입니다. 여러분이 폰트 ID 를 쓰고 싶으실 때는 fid 멤버값을 사용하세요.

XSetFont 함수를 사용하실 때는 바로 폰트 ID 를 사용하셔야겠죠?

일단 구조체에다가 몽땅 폰트 관련 정보를 가져왔으므로 이제는 어떤 정보를 알아 내기 위해 X 서버와 통신할 필요가 없다는 장점이 있습니다.

여러분이 XFontStruct 구조체를 가지고 계시면 다음과 같은 함수들을 통해서 여러가지 정보를 캐내실 수 있습니다.

오늘의 설명은 여기서 마치기로 하겠습니다. 사실 폰트에 대한 설명은 그림을 보여 드리면서 하는 것이 필요하다는 생각이 드는군요. 서점에 가보시면 많은 참고 서적이 있으므로 그냥 슬쩍 폰트 Property 에 관한 부분을 잘 살펴보시기 바랍니다.

그리고 한글 프린팅을 위해서는 한텀 소스의 hangul.c 부분을 잘 훑어보시기 바랍니다. 또는 한글 fvwm 2.0.42 소스에서 libs 디렉토리에 가보시면 HangulSupport.c 라는 것이 있습니다. 그것을 살펴보시던지요...


Previous Next Table of Contents