How to disable font hinting in Swing (or how to strip hints from a font)

In my GNOME desktop, I disable hinting or set hinting level to ‘slight’. The hinting level beyond ‘slight’ (i.e. ‘moderate’ or ‘full’) makes glyph look too thin to read easily. Moreover, especially when screen DPI is high, unhinted or slightly hinted glyphs look much more beautiful than fully hinted ones:

If you think fully hinted one looks better or you are using Mac OS X, you are so lucky that you can skip this article. My font preference is often a problem to Java Swing based applications such as IntelliJ IDEA (and that was always why I go back to SWT-based Eclipse). Although Swing uses Freetype to render glyphs, which is the same library that GTK uses to render glyphs, it doesn’t seem to respect my font appearance settings:

This issue was raised a couple times in the community, but the latest OpenJDK 7 snapshot still doesn’t seem to fix this issue unfortunately. Therefore, there’s no way currently to disable font hinting in Sun/Oracle JDK or OpenJDK on Linux. What’s possible is working around the problem by stripping the hinting information out from your font files so that Swing does not apply any hinting because of the missing information.

To strip the hinting information from a TrueType font, you can use FontForge:

  1. Open your TTF file with FontForge.
  2. Press CTRL+A to select all glyphs.
  3. Choose Hints -> Clear Hints menu item (and wait for a while)
  4. Choose Hints -> Clear Instructions menu item (and wait for a while)
  5. Choose File -> Generate Fonts menu iteam and replace the existing font with the unhinted one.

If you don’t want to replace the existing font, press CTRL+SHIFT+F to update the metadata before the last step. A ‘Font Information’ dialog will show up and you can edit font names there.

Once the new fonts are generated, you can update your ~/.fonts.conf to make the unhinted fonts your default desktop:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <!-- Note that I actually appended 'U' to all unhinted font names -->
  <match target="pattern">
    <test qual="any" name="family">
      <string>sans-serif</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>Liberation Sans U</string>
      <string>WenQuanYi Zen Hei U</string>
    </edit>
  </match>
  <match target="pattern">
    <test qual="any" name="family">
      <string>sans-serif</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>Liberation Serif U</string>
      <string>WenQuanYi Zen Hei U</string>
    </edit>
  </match>
  <match target="pattern">
    <test qual="any" name="family">
      <string>monospace</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>Liberation Mono U</string>
      <string>WenQuanYi Zen Hei U</string>
    </edit>
  </match>
</fontconfig>

If configured properly, hinting will be automatically disabled for all desktop applications soon no matter what hinting option you specified because there’s no hinting information in the new fonts.

Now open or restart your favorite Swing application and choose GTK Look & Feel. If you have to specify the font name explicitly, choose the unhinted one (e.g. Liberation Mono U). The result is your new-born Swing application with its ever-pleasing look:

Actually, the italicized bold glyphs doesn’t look perfect, but I can live with it. It would be really nice if OpenJDK delivers a proper fix in the near future, though.

Advanced Bash-Scripting Guide in ePub and MOBI format

Mendel Cooper’s Advanced Bash-Scripting Guide is the most definitive and up-to-date guide for Bash. If you are interested in some advanced topics in shell scripting, this book is for you.
However, if you prefer to read a document in your e-book reader such as Kindle and Sony Reader, you are in trouble because the guide is only provided in TXT, HTML, PDB, and PDF / PS format. PDB is the closest thing to the modern e-book formats, but it seems like there’s no good free converter yet.
Good news is, because I really wanted to read it in my Kindle, I converted it into ePub and MOBI format. Download them here:

Unfortunately, the conversion was done manually, so I’m not sure I’ll update it again when a new version is released since the guide is already good enough for me. Hopefully, once the author converts the SGML source into XML and DocBook ePub stylesheet matures, the conversion will be much simpler and completely automatic.

최고의 순간은 오지 않았다

요즘은 ‘최고의 순간은 아직 오지 않았다’ 라는 말을 자주 되새긴다. 이 말은 여러 곳에서 자주 나오지만 나는 브리짓 존스의 일기사운드트랙 중 한 곡인 Dina Carroll 이 부른 Someone Like You 에서 처음 접했다.

방향을 잃고 무너져가는 것 같은 순간이 오면 그 말을 되새긴다. 무엇이든 진지하게 해 나아간다면 스스로에게 있어 최고의 순간은 매일 찾아오는 것에 다름없음을 어리석으나마 재차 깨닫는다. 좋은 결과가 따라온다면 더 좋겠지만 그렇지 않아도 상관은 없다. 나 자신의 주인이 되는 것만큼 즐거운 것은 없다.

아무리 그렇다고 해도 매일 매일 맞딱뜨리는 고민과 갈등이 하나도 힘들지 않다면 거짓말이다. 가족이나 친구처럼 기댈 수 있는 존재가 있기에 이런 달콤한 이야기도 할 수 있다. 매일 매일 찾아 오는 최고의 순간이라면 매일 매일 함께 축하하고 축하받고 싶다.

WebSocket 기반 쌍방향 메시징

이제는 많이들 HTML5 나 WebSocket 에 대해 들어보셨을 것으로 압니다. 하지만 실제로 웹에서 쌍방향 통신을 구현하기 위해 WebSocket 을 이용해 보신 분들은 아직 많지 않으실 텐데요. 지난 7월 8일, 월간 마이크로소프트웨어에서 주관한 JBoss 세미나에서 WebSocket 프로토콜과 그에 기반한 쌍방향 통신 클라이언트 / 서버 개발에 대해 발표한 자료를 공유합니다. 도움이 되시길 빕니다.

혼자 보내는 밤

요즘은 아내가 장거리 출퇴근을 한다. 그래서 피곤하거나 일이 많으면 기숙사에서 자고 올라오기도 한다. 고된 업무로 병을 얻거나 하지는 않을까 걱정스럽다.

혼자 밤을 보낸다는 것은 다소간의 불면과 함께 묘한 감정을 불러온다. 인정하기는 쉽지만 받아들이기는 어려운 불확실한 인생사에 심경이 복잡해지기 마련이다.

복잡한 마음에 기대 고민거리를 이리 저리 끄적여 본다. 하지만 털어놓으려고 하면 할 수록 사람들이 보통 하는 고민과 다를 바가 없음을 깨닫는다. 게다가 별다른 진전조차 없지 않은가.

소프트웨어를 개발할 때는 문제를 좀 더 잘 이해하고 다양한 해결책을 평가하기 위해 마인드 맵과 같은 도구를 이용해 왔다. 지금까지 그보다도 훨씬 복잡한 인생사에 아무 준비도 없이 겉도는 고민만 한 것은 아닐까.

단순히 어지러운 마음을 토로하는데 그치지 않고 진지한 자세로 끈기있게 고민하며 해결에 임해야겠다.

일상풍경

누구나 하고 싶은 일을 하기를 원한다. 대단히 즐겁기 때문이다. 돌이켜보면 지금껏 하고 싶은 일을 해 왔고, 내키지 않는 일이 있으면 하고 싶은 일을 할 수 있는 곳으로 갔던 것 같다.

그러나 요즘처럼 딱히 하고 싶은 일이 없는 상황에서는 무엇을 어떻게 해야 할 지 모르겠다.

삶이 한가하다 못해 지루하게 느껴진다. 다시 바빠져야 할 이유를 딱히 찾을 수 없다. 심지어 지루한 것이 그렇게 나쁜 것 같아 보이지 않기까지 하다.

나는 변화를 기다리고 있는가, 그냥 웅크리고 앉아 있는가 – 특별할 것 없는 하루가 또 지나간다.

향수병은 언제나 있는 법

Whatever happened to programming?

읽으면서 드는 생각은 ‘언제나 향수병은 있는 법이다.’

그 때나 지금이나 누군가가 만들어 놓은 기반 위에서 작업하는 것은 변함이 없다. 그럼에도 그 때가 그리운 이유는 현실과 이상의 괴리 때문이 아닌가?

안정된 직장을 버리고 연봉은 절반으로 낮추고 펀드 / 저축 해지하고 스타트업으로 옮기기엔 리스크가 크다. 남는 시간에 무언가 해 보고자 하지만 이제 24시간 PC 를 붙들고 살 수는 없다. 그래서도 안된다.

학생이거나 초년생일때와는 다르다. 부모님은 이제 늙으셨고, 이젠 우리가 돌봐야 할 사람들이 더 많다. 쉽게 바뀌지 못하는 기성에 대한 분노가 많은 경우 부족한 경험에의 반증이었음을 이제는 안다.

지금도 변화를 갈망하지 않는 것은 아니다. 그러나 일과 삶의 공생을 이루지 않고서는 불가능함을, 그리고 그것은 처음 시작하는 것 보다 훨씬 복잡하고 어려운 과정임을 마음이 시리도록 잘 알고 있을 따름이다.

Setting up a Forwarding DNS Server (or DNS Proxy) with ISC BIND

When you are connected to VPN, all DNS queries in your system often goes to the DNS server that your company runs. This is inefficient because most DNS queries can be resolved by faster public DNS servers such as Google Public DNS. If only the domain names related with your company are resolved by the private name servers, you won’t have a problem browsing public web sites due to an unstable VPN connection.
To address this issue, you can install a forwarding DNS server (a.k.a. proxy DNS server) in your machine or local area network. There are dedicated DNS proxy servers such as pdnsd and dnsmasq, but I recommend to use BIND because it was more reliable than others from my experience. Unlike the first impression, BIND is very easy to configure into a forwarding DNS server. Moreover, BIND works fine on both Windows and Linux.
First, let’s say we want to forward all DNS queries to Google Public DNS (8.8.8.8 and 8.8.4.4):

# /etc/named.conf
options {
    directory "/var/named";
    # Hide version string for security
    version "not currently available";
    # Listen to the loopback device only
    listen-on { 127.0.0.1; };
    listen-on-v6 { none; }; # No IPv6
    # Do not query from the specified source port range
    # (Adjust depending your firewall configuration)
    use-v4-udp-ports { range 32768 65535; };
    use-v6-udp-ports { range 32768 65535; };
    # Forward all DNS queries to the Google Public DNS.
    forwarders { 8.8.8.8; 8.8.4.4; };
    forward only;
    # Expire negative answer ASAP.
    # i.e. Do not cache DNS query failure.
    max-ncache-ttl 3; # 3 seconds
    # Disable non-relevant operations
    allow-transfer { none; };
    allow-update-forwarding { none; };
    allow-notify { none; };
};
# Disable the control channel.
controls { };

If you are connected to your company VPN and you want to forward some DNS queries for certain domains to different name servers, you can override the default settings by adding the zones for your company domains:

... (continuing from the named.conf above) ...

zone "abc.com" in {
    # matches:
    #     abc.com
    #     intranet.abc.com
    type forward;
    forwarders { 192.168.1.1; 192.168.2.2; };
};

zone "private.def.com" in {
    # matches:
    #     private.def.com
    #     mail.private.def.com
    type forward;
    forwarders { 172.10.1.1; 172.10.2.2; };
};

If you don’t want to forward some subdomain of the overridden zones to the private DNS servers, you can insert another zone before the zone definitions above to override the override:

zone "www.abc.com" in {
    type forward;
    forwarders { 8.8.8.8; 8.8.4.4; };
}

zone "abc.com" in { ... }

Here’s my complete configuration. Please note that I replaced the domain names and the private DNS server addresses with bogus values.

options {
    # I am running BIND on Windows without a problem. :)
    directory "C:\Program Files (x86)\BIND\etc";
    version "not currently available";
    listen-on { 127.0.0.1; };
    listen-on-v6 { none; };
    use-v4-udp-ports { range 32768 65535; };
    use-v6-udp-ports { range 32768 65535; };
    forwarders { 8.8.8.8; 8.8.4.4; };
    forward only;
    max-ncache-ttl 3;
    allow-transfer { none; };
    allow-update-forwarding { none; };
    allow-notify { none; };
};
controls { };
# We can't resolve the VPN server names with the private
# DNS servers before we join the VPN, so we should use
# the public DNS to initiate VPN connection successfully.
zone "vpn.abc.com" in {
    type forward;
    forwarders { 8.8.8.8; 8.8.4.4; };
};
# Our company has two top level domains: abc.com and def.com
zone "abc.com" in {
    type forward;
    forwarders { 172.10.1.1; 10.10.2.2; };
};
zone "def.com" in {
    type forward;
    forwarders { 172.10.1.1; 10.10.2.2; };
};

At last but not least, make sure to set the DNS settings in your operating system to point to the DNS server you’ve just configured (i.e. 127.0.0.1). In Linux, you should update /etc/resolv.conf or your NetworkManager settings. In Windows, you know what to do – mess with the Control Panel. 🙂

심호흡

방향을 잃은 듯 흔들리는 마음 때문일까? 새해가 되면 흔히 보이는 결심이라든지 하는 것들을 올해는 시야에서 찾아보기 힘들다. 잠깐 스쳐 지나가듯 그저 무디게만 느껴진다.

스스로를 감탄시킨 성취도 계속되는 일상 속에 묻혀 과거가 된다. 가끔은 그 속도가 놀라워서 묻힌다기보다는 매몰된다는 표현이 어울릴 정도다. 아니, 매몰‘시킨다‘고 하는 쪽이 더 정확할 것 같다. 나는 감격에 겨웠던 성공이나 깨달음의 순간들에 쉽게 싫증을 내고 대수롭지 않게 여기는 편이다.

더 성취하고 싶어서 마음이 앞서는 날이 있다. 하는 일 없이 반복되는 일상에 염증을 느낀다. 바꾸고 싶어도 마음처럼 되지 않아 화가 난다. 괜히 주변의 사람이 미워진다.

숨을 깊이 들이쉰다.