'장난감들'에 해당되는 글 4건
- 2008/07/11 PuTTY 한글/영문 글꼴 분리하기 (5)
- 2008/06/27 Supreme Commander 한글입력기 구현하기 (2)
- 2008/02/09 PNG Color Profile Removal Tool (1)
- 2006/09/07 Simple Tooltip Class (2)
PuTTY 한글/영문 글꼴 분리하기
오늘도 삽질 하나. 날씨도 너무 덥고 텍스트큐브 코딩도 안 되고(?) 해서 PuTTY를 뜯었다.;; 그동안 오랜 숙원사업(?)이었던 한글/영문 글꼴의 완전한 분리에 성공했다.
스크린샷. 전체 사이즈 보려면 여기 클릭.
PuTTY 소스코드가 생각보다 난잡(...)해서 찾는 데 좀 시간이 걸렸지만 더위는 이열치열(?)이라는 생각으로 삽질을 해주니 마침내 어디를 고쳐야 하는지 찾을 수 있었다.
방법은 간단히 다음과 같이 window.c를 패치해주고 컴파일하면 끝.;; 보다시피 급조한 거라 글꼴 설정은 소스코드에 하드코딩되어 있다; 기준 소스는 0.60 최신 버전. 아참, 생성만 하고 소멸시키지 않는 것처럼 보이나 다른 부분에 보면 FONT_MAXNO까지 배열을 순회하며 DeleteObject를 호출해주는 부분이 있으므로 걱정 안 해도 된다.
//...
#define FONT_OEMBOLDUND 0x23
#define FONT_NONLATIN 0x30
#define FONT_MAXNO 0x30 //0x2F
//...
static void init_fonts(int pick_width, int pick_height)
{
//...
f(FONT_NORMAL, cfg.font.charset, fw_dontcare, FALSE);
fonts[FONT_NONLATIN] = CreateFont (font_height, font_width, 0, 0, fw_dontcare, FALSE, FALSE, FALSE, \
cfg.font.charset, OUT_DEFAULT_PRECIS, \
CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg.font_quality), \
FIXED_PITCH | FF_DONTCARE, "Dotum");
SelectObject(hdc, fonts[FONT_NORMAL]);
GetTextMetrics(hdc, &tm);
//...
}
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
//...
} else {
/* And 'normal' unicode characters */
static WCHAR *wbuf = NULL;
static int wlen = 0;
int i;
if (wlen < len) {
sfree(wbuf);
wlen = len;
wbuf = snewn(wlen, WCHAR);
}
for (i = 0; i < len; i++)
wbuf[i] = text[i];
/* EXTRA PATCH for non-latin font replacing... */
SelectObject(hdc, fonts[FONT_NONLATIN]);
text_adjust = 1;
/* print Glyphs as they are, without Windows' Shaping*/
general_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust,
&line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING));
//...
}
유니코드 렌더링 부분을 바꾼 것이기 때문에 CP949나 윈도98과 같은 환경에서는 어떻게 나오는지 모르겠지만 일단 나는 유니코드 터미널만 쓰고 있으므로 패스; =3
내가 VS2005로 컴파일한 바이너리는 KLDP를 참조하기 바란다.
추가: 앞으로 원활한 개발을 위해 공개 subversion 저장소를 생성하였다. ViewVC를 통해 살펴보려면 이 링크를 참조하기 바란다. SVN 프로토콜로 접근하려면 경로에서 view를 빼면 된다.
Supreme Commander 한글입력기 구현하기
드디어 슈프림 커맨더(Supreme Commander)의 한글입력기를 구현했다. 이 게임은 오리지날 버전(영어권에서는 Vanilla라고 부른다)은 한글화 번역이 이루어져 출시가 되었으나 번역의 질이 굉장히 낮았고 특히 한글 채팅이 전혀 지원되지 않아 많은 유저들의 불만을 샀다. 그나마 많이 팔리지도 않아 확장팩인 Forged Alliance의 경우 아예 국내 출시조차 이루어지지 않았고, 결국 나(...)를 비롯한 매니아들은 해외 직수입 게임 전문점이나 지인을 통한 구매대행 등을 이용할 수밖에 없는 상황이다.
아무튼 그동안 한국 유저들의 오랜 갈망이었던 한글 채팅을 User Interface mod 형식으로 구현하는 데 성공했다. 슈컴이 워낙에 modding 확장성이 좋다고 알려져 있기는 했지만, 실제로 이번 기회를 통해 만져보니 정말 잘 만들었음을 알 수 있었다. 게임의 핵심적인 구동 엔진을 제외하고 나머지 다른 부분들—유닛의 움직임, 게임 시나리오, UI, 인공지능 등등—상당히 많은 부분이 lua 스크립트 언어를 통해 만들어져 있다. 게임 데이터들은 *.scd라는 파일에 들어있는데 이것은 실상 그냥 zip 압축파일이라서 누구든지 풀어볼 수 있도록 하고 있다. (별도의 복잡한 암호화 이런 거 없다.)
실제로 이번에 한글입력기 mod를 제작해보니 게임 내부가 어떤 로직으로 돌아가는지 거의 다 들여볼 수 있을 정도로 개방적이었다. 그만큼 게임 품질에 자신감이 있다는 뜻일 수도 있겠다.
요즘 게임 내부 스크립트 엔진용으로 많이 쓰이는 lua는 그러나 약간 실망이었다. 함수형 언어의 특징을 강하게 가지고 있는 lua는 어찌보면 ruby와도 상당히 비슷하다. 하지만 실제로는 매우 단순화된 언어로, 자료 구조라고는 오직 dictionary와 비슷한 table밖에 지원하지 않고, 비트연산자 등 다른 언어에는 당연히 있을 만한 기능들이 없는 경우가 꽤 있다. 유니코드 인코딩도 지원하지 않아 결국 utf-8 인코딩 루틴까지 직접 다 짜야했다. 대신 그 table 자료구조가 굉장히 강력하여(metatable이라는 개념을 제공한다) 함수형 언어의 특징과 결합해 이것만으로 class라는 개념을 언어에 도입하는 것이 가능할 정도이다.
오토마타 루틴은 예전에 CS322 과목 프로젝트로 Python으로 구현한 한글입력기(정확히는, 영타로 입력된 문자열을 한타로 변환하여 한글 문자열로 만들어주는..)를 lua로 그대로 포팅하였다. 둘의 문법이 비슷하여 큰 어려움은 없었고, 다만 lua에서는 table의 index가 0이 아니라 1부터 시작한다는 점 때문에 조금 헷갈리는 정도였다.
걸림돌이 되었던 부분은 오토마타의 결과물로 나온 unicode 숫자 배열을 실제의 utf-8 문자열로 변환하는 것이었는데, 이 과정에서 나머지 연산과 shift 연산이 필요하여 결국 수동으로 구현해야 했다. 특히 lua의 숫자는 무조건 double이고 라이브러리에서 필요시 unsigned long으로 바꾸는 식이기 때문에 나눗셈을 수행할 때 항상 math.floor를 해줘야 한다.
local function modulo(a, b)
return a - math.floor(a/b) * b
end
와 같이 구현할 수 있고, right shift 연산의 경우 간단하게 2의 제곱승으로 나눠주면 된다.
혹시 필요한 분들을 위해, unicode 숫자가 순서대로 담긴 table을 입력으로 받아 utf-8로 인코딩된 문자열로 내놓는 함수를 소개한다. (테스트는 엄밀하게 해보지 않았지만 적어도 한글은 잘 나온다. =3=3)
function conv2utf8(unicode_list)
local result = ''
local w,x,y,z = 0,0,0,0
local function modulo(a, b)
return a - math.floor(a/b) * b
end
for i,v in ipairs(unicode_list) do
if v ~= 0 and v ~= nil then
if v <= 0x7F then -- same as ASCII
result = result .. string.char(v)
elseif v >= 0x80 and v <= 0x7FF then -- 2 bytes
--[[
y = (v & 0x0007C0) >> 6
z = v & 0x00003F
]]--
y = math.floor(modulo(v, 0x000800) / 64)
z = modulo(v, 0x000040)
result = result .. string.char(0xC0 + y, 0x80 + z)
elseif (v >= 0x800 and v <= 0xD7FF) or (v >= 0xE000 and v <= 0xFFFF) then -- 3 bytes
--[[
x = (v & 0x00F000) >> 12
y = (v & 0x000FC0) >> 6
z = v & 0x00003F
]]--
x = math.floor(modulo(v, 0x010000) / 4096)
y = math.floor(modulo(v, 0x001000) / 64)
z = modulo(v, 0x000040)
result = result .. string.char(0xE0 + x, 0x80 + y, 0x80 + z)
elseif (v >= 0x10000 and v <= 0x10FFFF) then -- 4 bytes
--[[
w = (v & 0x1C0000) >> 18
x = (v & 0x03F000) >> 12
y = (v & 0x000FC0) >> 6
z = v & 0x00003F
]]--
w = math.floor(modulo(v, 0x200000) / 262144)
x = math.floor(modulo(v, 0x040000) / 4096)
y = math.floor(modulo(v, 0x001000) / 64)
z = modulo(v, 0x000040)
result = result .. string.char(0xF0 + w, 0x80 + x, 0x80 + y, 0x80 + z)
end
end
end
return result
end
PNG Color Profile Removal Tool
이거 상당히 오래된 주제이긴 한데, 막상 필요할 때 대충 찾아서 쓰려고 해보니 윈도 전용으로 나온 것이 많아 cross platform으로 간단히 쓸 수 있도록 python 스크립트로 짰다.
주요 기능은 PNG 파일 포맷에서 색상 calibration 정보를 나타내는 필드들을 삭제해버림으로써 IE 및 Safari에서 gamma 값을 해석하지 않아 발생하는 색상 불일치 문제를 해결하는 것이다. 사용법은 python pngtool.py --help해보면 알 수 있다.
Simple Tooltip Class
tooltip.jsSimple Tooltip Script
사용법은 아주 간단하다. window.onload와 같은 이벤트에서 initTooltips() 함수를 호출해주면, 자동으로 페이지에 있는 모든 a 태그를 검사하여 title 속성이 있는 태그에 대해 툴팁을 달아준다. 이때 새로운 div 태그가 body에 하나 추가되는데, 이 태그는 tooltip이라는 class로 설정되므로 style sheet에서 적절하게 디자인을 정의해주면 된다. (평상시엔 보이지 않는 태그이므로 페이지의 레이아웃에는 전혀 영향을 주지 않는다)
그렇게 하면 마우스를 링크에 가져다 대었을 때 Windows XP의 툴팁처럼 투명도 애니메이션이 진행되는 툴팁을 볼 수 있을 것이다. moo.fx를 확장한 moo.fx.pack을 쓴다든가 하면 더 화려한 효과를 제공할 수 있다. 다만, mouseout 이벤트 발생 시, 툴팁을 숨겨야 하는데 마우스를 빨리 움직여 다른 링크에 mouseover 이벤트가 발생한다든가 하면 툴팁이 화면에 남아있거나 깜빡거리는 문제가 있어서, 서서히 사라지는 효과는 넣지 않았다. (이에 대한 처리는 moo.fx에서 제공하는 clearTimer 메소드를 이용해 애니메이션을 강제 중단시키는 방법을 사용하였다. 만약 툴팁 div element를 하나만 쓰지 않고 각 링크마다 생성하여 쓴다면 해결할 수 있을지도 모르겠다.)
확실히 prototype과 같은 javascript framework를 써보니까 편하다. Cross-browsing을 전혀 신경쓰지 않고 원하는 대로 구현할 수 있기 때문이다. 여기에 moo.fx라는 매우 작고 강력한 animation library까지 있으니 더할나위 없다. 나중에는 Yahoo UI library도 한 번 써봐야겠다.
ps. 만들 때 Firejune님 블로그의 툴팁 소스를 참조했다. 너무나 복잡한 기능이 많아서 아주 간단하게 정리해본 것이다.

이올린에 북마크하기
이올린에 추천하기



