삽질하는플머

다국어 입력... 또 하나의 산.

탐구생활/Uniscribe
델마당 겜제작란에 올린 글을 옮겨붙여둠. 

솔직히 지금까지 출력만 잘 해결하면 입력은 윈도가 알아서 해주는 줄 알았는데...
글립엔진을 붙이고 있는 막내가 낑낑거리기에 참견하러 갔더니, 태국어 입력이 엉뚱하게 처리되고 있더라구요. 

앞서 이 길을 걸어가셨던 엘비스님께 도움을 청하니... "응? 그냥 되던데요?" 
태국어에 대해 Zupet님이 남기신 주옥같은 글에는... "그냥 WM_CHAR를 받아 찍으면 된다~"

두 분 모두 키워드는 "그냥~" 음냐... 도대체 안되는 이유가 뭘까 고민하니... 
아... 저희 게임윈도는 유니코드기반이었습니다. 2년쯤 전 중국어 간체로 된 게임제목이 한글윈도에서 깨져보이는 게 짜증나 바꿔버렸습죠. 로케일을 특정 국가로 고정하고 안시 API를 사용할 때에는 입력된 CharCode값을 해당 국가코드로 간주해 조립하면 되지만, 동시에 여러국가 언어를 입력받기 위해 유니코드 지원 윈도를 만들었을 때는 얘기가 다르더라구요. wParam의 LoWord에  255가, HiWord에 해당 UCS2 코드가 박혀날아옵니다. 이걸 Char로 형변환해 찍었으니 요상한 글자가 나올 수 밖에요. 어흙... 

일단 여기까지 해서 한시름 놓았는데... 다시 또 하나의 산이 가로막습니다. 태국어 입력기를 설치하고 'i' 'e' 를 차례로 입력하면 아래와 같은 글자가 찍힙니다. 

รำ

두 개 처럼 보이지만 뒤에 붙은 놈은 앞의 글자를 꾸며주는 물건이고 때문에 이 글자는 하나의 글자입니다. 그런데 여기에 다시 'e'를 눌러보면 어떻게 될까요. 표준 윈도 컨트롤을 제외한 입력창, 심지어 지금 제가 글을 적고있는 구글 크롬에서도 빈 문자가 뒤에 적층됩니다. 때문에 백스페이스로 글자를 지우려 하면 'e'를 누른 횟수만큼 커서가 제자리에 멈추게 되지요. 


รำรำรำ
รำำำรำำำรำ


위의 두 문자는 겉보기에는 똑같이 생겼지만 메모장같은 곳으로 복사해 백스페이스로 지워보면 처음것은 여섯번, 두번째 것은 열 번을 눌러야 지울 수 있습니다. 즉 이런 입력은 허용되어서는 안된다는 얘기입니다. (아이폰용 사파리에서는 입력한 대로 보이는군요.)  

막내와 머리를 쥐어짜기 시작했습니다. 처음에 떠오른 생각은 태국어의 조합원리를 조사해 예외처리를 하자는 것... 하지만 이 방법은 아무리 삽질을 좋아하는 저도 썩 내키지 않더군요. 그래서 새로운 글자가 입력되기 전과 후의 글립모양을 살펴서 동일할 경우 입력을 취소하자는 꽁수를 떠올렸습니다. 이 때 글립폭이 0인 녀석들은 제외하면 실제 보이는 모양만 비교할 수 있겠다 싶었지요.

그런데... 'i' 와 'h'를 입력할 경우처럼 두번째 글립이 앞부분에 옵셋되어 합쳐질 때, 

ร + ่ = ร่

이런 경우 유니스크라이브는 두번째 글립의 폭이 0이라고 알려줍니다. 하지만 모양이 틀림없이 변하므로 빼고 생각할 수는 없습니다. 결국 실제로 폰트에서 뽑아낸 글립의 크기값이 필요해지네요. 유니스크라이브의 고수준 API인 ScriptString을 쓰지 못하는게 처음에는 많이 아쉬웠는데... 그 때 휘둘렀던 삽자국이 이리도 유용하게 쓰일줄은 몰랐습니다. 흐흐흐~~

사실 크롬도 동일한 현상을 보인다는 걸 미리 알았다면, 그냥 사용자가 조심해서 쓰라고 하고 끝냈을텐데... 그건 이 글을 적으면서 깨달은거니... ^^;;

암튼 짧지만 굵은 삽질기였습니다. 솔직히... 이런거 갖고 고민할때가 제일 재미나는 것 같아요~~ 


기존 게임용 문자 상자 (TextBox) 구현

탐구생활/Uniscribe
유니스크라이브 삽질에 비해 상대적으로 쉬워보이는 문자열 출력도 이것 저것 신경쓰려다 보니 계속 할 일이 생긴다.
모든 일이 다 그렇지만... 제대로 하려고 마음 먹으면 끝이 없는듯 하다.

게임에서 NPC 대화상자등을 만들 경우도 쉽게 하려면 화면너비 기준으로 일일이 잘라넣으면 되지만, UI 가 변경되거나 할 경우 다시 수정해야 하는 번거로움이 있다. 때문에 적절한 워드랩을 지원해주면 로컬라이징 작업이 많이 행복해진다.

유니스크라이브의 ScriptBreak() 함수를 쓰면 문자열의 특정 위치에서 캐럿이 위치할 수 있는지, 단어 분리점인지, 라인브레이크가 가능한지 등의 정보가 기록된 SCRIPT_LOGATTR 의 배열을 얻을 수 있다. 이 중 라인브레이크 정보를 써서 문자 상자 (TextBox) 를 만들어 보았다. 




상자의 폭을 줄이면 넘치는 글자는 다음줄로 흘러내려간다.




가운데 정렬.




우측 정렬.




우측 정렬 하면 빼놓을 수 없는 아랍어 테스트.




태국어의 단어단위 워드랩도 일단은 제대로 동작하는 것 처럼 보인다.
(뭔 뜻인지 알 수가 없으니 메모장과 비교해 볼 수 밖에...)




장평 150% + Blur:R2




장평 70% + Blur:R2




------

오래전 엘비스님과 태국어 출력에 대해 이야기하다 GPG에 올렸던 글이 생각났다.
http://www.gpgstudy.com/forum/viewtopic.php?p=106336

별다른 설정을 하지 않았음에도 윈도의 워드패드나 우분투의 GEdit 에서 워드 브레이크가 동작하는 것이 신기해서 올렸던 글이었다.
생각해보면 유니스크라이브라는 명칭을 처음 들었던 곳도 GPG였는데...

예를 들면 이런 고민의 흔적들...
http://www.gpgstudy.com/forum/viewtopic.php?p=25873 
솔직히 이렇게 "나는 이제 알지만 말해주기는 싫어" 같은 글들을 참 싫어한다. 그래도 험한 등산로 나뭇가지에 매어둔 리본정도의 역할은 되는 듯 하다. 적어도 어디로 가야하는지는 알려주니까.

당시 백업소스를 뒤져보니 리치에디트를 동적으로 생성하고 문자열을 복사해넣은 뒤 캐럿의 위치와 워드 브레이킹 정보를 얻는 코드도 있군. 크핫~~!

------

까칠한 PM 덕에 금칙어 처리도 신경써야 할 듯 하다. 수많은 정보를 처리해주고 복잡하게 꼬여있는 유니스크라이브가 왜 금칙어에 대해서는 무시하고 있을까... 아직 못찾은 것일지도 모르지. 으으...

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

탐구생활/Uniscribe
한 일

미루어두었던 패스워드 캐릭터 마무리.





테스트삼아 구현해 본 장평. 하나의 폰트로 여러가지 느낌을 줄 수 있어서 의외로 쓸만할 듯.
(자간의 경우는 출력오토마타 문자열에서 문제가 있어 일단 보류. 대학때 레포트의 비결이던 신명조 장평 95% 자간 -5 가 떠오르네.)
 





에디터에서는 써먹을 일이 거의 없겠지만, 글립 랜더링 옵션도 지정할 수 있게 함. 






이제 기획자들이 써먹을 수 있도록 루아스크립트 연동코드만 매달아주면 되겠다.

==============================
2010.8.3

루아 연동코드 추가 완료. 이제 당분간 마음 편하게 미루어두었던 삽질들을 할 수 있겠군.

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

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

한 일

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





우측정렬 구현.


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



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


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






할 일

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

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

--------

마우스 메시지 처리 완료.

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

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


--------

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

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

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

탐구생활/Uniscribe

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



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


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


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



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

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