삽질하는플머

기존 게임용 에디터 구현... 2.

탐구생활/Uniscribe
지난번에 이어서

한 일

힌두어, 태국어, 아랍어등 출력오토마타 문장에서의 백스페이스 처리.





우측정렬 구현.


IME 처리. 조합시 언더라인, 조합커서, 후보창위치 등.



선택박스 구현.
  (아랍어 등의 RTL 혼용 테스트. 머리 다 빠짐...)


  (컨트롤 + 화살표로 태국어 단어단위 선택 테스트.)






할 일

마우스 메시지 처리.
패스워드문자 구현.

우우... 선택박스에서 힘을뺐더니 귀차니즘이 밀려온다...

--------

마우스 메시지 처리 완료.

패스워드 처리를 위해 생각을 정리하다보니... 랜더링, 커서처리, 마우스처리등을 이중으로 관리하느라 구조가 지저분해진다. 내부문자열을 단순히 "*" 로 대체해서 찍기 위해 이런 수고를 하는 것 보다... 그냥 패스워드 처리 전용 에디터를 하나 더 만드는 편이 맞을 듯 싶다. (생각해보니 예전에도 같은 고민에 같은 결론을 내렸던 것 같다.)

최대길이값을 제한하는 코드만 추가하고 마무리짓자.


--------

MaxLength 처리 완료.
최대값 근방에서 IME 입력 다루기가 거지같네... 특히 일본어처럼 조합문자열이 복수인경우... 예전에도 이게 귀찮아서 안했었는데...

이제 깔끔한 마음으로 술먹으러 가야지...

기존 게임용 에디터 구현... 1.

탐구생활/Uniscribe

글립캐시 DLL을 사용한 에디트 컨트롤을 구현중. 수개월동안 머릿속에서만 돌아가던 물건이 조금씩 완성되는 기분은 참 좋다. 하긴 뭐... 이 맛에 코딩 하는거지만...



한 일.
출력 처리.
키다운 메시지 처리.
글자단위, 단어단위 캐럿 이동.
캐럿 이동에 따른 문자열 옵셋 처리.
복사/잘라내기/붙이기


할 일.
IME 메시지 처리.
마우스 메시지 처리.
선택박스 구현.
패스워드문자 구현.


사실 제일 난감한부분이 바로 "선택박스"인데... 예전에는 그냥 선택시작위치에서 선택된 양 만큼 역상시키면 그만이었지만 LTR, RTL이 뒤섞인 상황에서는 그게 말처럼 쉽지가 않다. 아래 이미지는 위의 문자열을 워드패드에서 선택해 본 것이다.



RTL인 아랍어는 선택상자가 좌측으로 뻗어나가다가 LTR인 영문을 만나 다시 우측으로 진행된 후 다시 아랍어를 만나 좌측으로 진행되고 있다. 유니스크라이브의 ScriptString API 에서는 ScriptStringOut을 쓰면 이 부분까지 자동으로 처리해주지만... 그저 군침만 흘릴 뿐... 

밤새 고민하면 내일쯤 대충 방법이 떠오르겠지 머~~

 

기존 게임으로 피드백

탐구생활/Uniscribe

글립 캐시를 외부에서 사용할 수 있도록 DLL로 만들고, 기존 게임의 랜더링엔진에 대한 아답터루틴을 구현한 뒤 간단한 문자열을 올려보았다. 입력기를 새로 만들는 것 보다 기존 게임에서 쓰이는 입력기의 글자출력부분만 바꿔치는 방법이 좀 더 빠른 작업이 될 것 같아서... 또 어차피 기존 게임도 아랍어 등의 다국어 처리는 필요하니까.




DLL의 크기는 일단 160kb. 폰트링크에 쓰인 MLang 이 COM 이므로, 이에 대응하는 코드를 LVCL에 짜넣으면 훨씬 작게도 만들 수 있을 것이다.

힌두어 + 아랍어 + 태국어도 테스트. 자알~ 출력된다. (뿌듯~ 뿌듯~)
예제문자열 : ठऑक्षझॉيُساوِيเข้าหน้าสู่หน้าหลัก




지나가는 팁 한조각.

구버전 델파이는 코드편집기에 안시문자열을 사용한다. 때문에 위와같은 문자열을 코드에디터에서 지정하기가 쉽지 않다.
UTF-8 편집을 지원하는 상위버전 델파이라면 #숫자 와 같은 형식을 WideString 에 바로 때려넣는것도 가능하지만 

  myWSTR: WideString =
    #2336#2321#2325#2381#2359#2333#2377#1610#1615#1587#1575#1608 +
    #1616#1610#3648#3586#3657#3634#3627#3609#3657#3634#3626#3641 +
    #3656#3627#3609#3657#3634#3627#3621#3633#3585;

구버전에서는 이또한 여의치 않다.

유니코드 구세주인 TNT컨트롤의 TntSystem.pas 에 정의된 다음 두 함수를 써보자. 

  function WideStringToUTF7(const W: WideString): AnsiString;
  function UTF7ToWideString(const S: AnsiString): WideString;

WideStringToUTF7 함수로 위의 다국어를 변환해주면 다음과 같은 안시문자열을 얻을 수 있다.

      '+CSAJEQkVCU0JNwkdCUkGSgZPBjMGJwZIBlAGSg5ADgIOSQ4yDisOGQ5JDjIOKg4' +
      '5DkgOKw4ZDkkOMg4rDiUOMQ4B';

코드를 안짜고 간단히 얻으려면, 빈 폼에 TTntEdit 를 하나 올리고 여기에 원하는 다국어를 넣어준 뒤 마우스 우측버튼을 눌러 "View as Text" 메뉴를 선택하면 Text_UTF7 프로퍼티에 생성된 문자열을 복사해올 수 있다.




이렇게 얻어진 문자열을 대충 다음과 같이 UCS2로 변환해쓰면 된다. 

const
  myASTR :  AnsiString =
      '+CSAJEQkVCU0JNwkdCUkGSgZPBjMGJwZIBlAGSg5ADgIOSQ4yDisOGQ5JDjIOKg4' +
      '5DkgOKw4ZDkkOMg4rDiUOMQ4B';
var
  myWSTR: WideString;
......
  myWSTR := UTF7ToWideString(myASTR);

뭐 구버전 델파이의 코드에디터에서 유니코드를 직접 지정할 일이 얼마나 될까 싶지만...
(적어도 오늘까지는 단 한번도 없었... ^^)

글립 랜더링 테스트.

탐구생활/Uniscribe
이미지 프로세싱을 거친 글립을 텍스쳐로 캐싱, 3D 화면에 올려보았다. 블러링된 그림자가 꽤 괜찮은 느낌을 주네.



블랜딩옵션과 색상을 조절하면 밝게 빛나는 느낌을 줄 수도 있다. 배경에 따라 적절히 써먹으면 좋을 듯 하다.



요렇게 해 주니 문질러서 군데군데 밝아진 느낌이 나는군.



한가지, 굴림 9~12 포인트 같은 놈들은 내부에 비트맵 정보를 따로 가지고 있다.
이 경우는 래스터라이징이 아닌 비트맵 폰트를 찍어주는 편이 훠얼씬 깔끔한데... 해당 크기에 비트맵정보가 있는지 여부를 판단하는 방법을 아직 찾지 못했다. 고민하다가 "Force Monochrome" 이라는 속성을 두었는데, 만들고 보니 이렇게 하는 편이 글자가 씌여지는 위치에 따라 적절한 선택을 하는 데 오히려 도움이 될 듯 하다. 캐릭터 머리위에서 늘어나고 줄어드는 글꼴은 항상 래스터라이징을, UI에서 고정된 글꼴은 모노크롬을 쓰는 방식으로 말이다.

굴림 12포인트.

굴림 12포인트. 모노크롬 강제모드. (앞의 것과 미묘하게 다름...)


테스트 프로그램은 여기. 글꼴은 10개, 문자열은 1000개, 폰트별 글립도 1000개 까지 캐싱하도록 설정되어있다.
기본글꼴은 Arial 이며 SetFont 버튼으로 변경할 수 있다. MLang에 의한 폰트링크를 시도하고 실패하면 폴백목록의 폰트를 뒤져 적절한 폰트를 찾는다. 폴백목록은 각 폰트별로 설정할 수도 있고 기본목록을 쓸 수도 있다. 여기서는 기본값으로 Tahoma, Arial, Verdana, Mangal, Gulim, Latha 를 지정해주었다. (명색이 3D인데 뒤에다 삼각형이라도 돌려줄 껄 그랬나... 조금 썰렁하군...)





유니코드 문자열을 입력하기 위해 TNT컨트롤을 쓰고 있는데... 터보델파이다보니 동적생성을 해야 해서 여러모로 귀찮다.
그래도 한번 손에 익으니 예전 환경으로 돌아가기가 싫으네~~

아무튼 이제 에디터를 만들어볼 차례~~

글립에 대한 간단한 이미지 처리 작업

탐구생활/Uniscribe
지금 게임에서는 글자의 가독성을 높이기 위해 그림자를 찍는 경우 동일한 글자를 검게 찍어준 뒤 그 위에 글자를 올리는 방법을 쓰고 있다.



그런데 사실 단순한 한개짜리 그림자는 게임 화면에 묻혀서 잘 보이지 않는다. 때문에 외곽에 테두리가 둘러진 글자를 많이 써먹게 된다.



위와 같은 이미지를 만들기 위해 상하좌우에 여덟번 검은글자를 찍고 가운데에 색깔글자를 찍어주는 방법을 쓰는데, 코드의 뽀대는 둘째치고 아무래도 효율이 떨어지게 마련이다. 채팅창같이 텍스트가 많이 쓰이는 곳에서는 검은색 상자를 블랜딩한 뒤 글자를  찍어주는 등 부하를 덜고는 있지만 내내 숙제처럼 머릿속에 남아있었다.

새로 만드는 글립엔진에서는 이런 부분을 개선해보기로 했다. 만들어지는 글립 하나하나에 적절한 처리를 하면 위에서 이야기한 비효율적인 상황이 나아질 듯 하다. 일단 글자를 뚱뚱하게 만들어 외곽을 그려주기 위한 '확장', 그리고 테두리를 추출하는 '아웃라인', 좀 더 뽀대나는 그림자를 위한 '가우시안블러' 를 구현해 보았다. 달구경 만들 때 구현했던 32비트 픽셀용 코드를 8비트용으로 고쳐 써먹고 있는데, 몇달 넘게 방치했던 놈들을 다시 들여다보려니 뭐가뭔지 한동안 헷갈...



위에서부터 차례로 기본, 픽셀확장, 픽셀확장+아웃라인, 픽셀확장+아웃라인, 픽셀확장+R2 짜리 가우시안 블러링된 글자이다.
블러링된 그림자 위에 기본글꼴을 찍어주면~~ 흠~~ 그럴듯하겠는데~~

부지런히 3D 환경에 찍어봐야겠다.