Font smoothing for CJK characters

In Chrome for Windows, there’s a problem in font rendering for CJK characters. When a font is displayed in large size, those jaggy edges can be quite annoying.

The cause of this problem lies in the font rendering engine in different browsers. IE uses DirectWrite, which supports subpixel rendering and bi-directional anti-aliasing, while Chrome uses GDI ClearType, which only supports horizontal subpixel rendering. Bas Schouten has blogged a detailed comparison between the two rendering technologies, which shows that DirectWrite usually yields smoother fonts.

CJK characters are more sophisticated than English alphabets, so some CSS tricks (or hacks) for fixing font rendering in webkit browsers can fail when dealing with those guys. For example, the text stroke fix does not make much visual difference to the text as can be seen here.

A working, yet imperfect, fix is tilting the font by a tiny degree to force Chrome use anti-aliasing.

div.antialiased {
  -webkit-transform: rotate(.1deg);
}

This method gives a pleasant result. It almost has the same quality as DirectWrite.

However, it transforms the text after all. In the example, when the text reaches 960px in length, the line end will be about 1.7px (calculated as: sin(0.1deg) × 960) lower than the start. Well, it may be unnoticable. Perfectionist may hate this I guess.

Notes on CSS positioning

By default, any element on a webpage is statically positioned. Top, left, right, bottom and z-index property are not effective with static positioning.

To use those properties, we need to set the position of the target element to relative. One thing to note here is that although an element with relative positioning can be visually moved, it is not moved from the document flow, which means other elements cannot take up the space given by the moved element.

Relatively positioned elements also set context for child elements with absolute positioning so that top, right, bottom, left and z-index property of those elements will be calculated based on the position of the parent. If the parent was statically positioned, those properties will be calculated based on the document element.

Absolutely positioned elements are moved from the document flow, so position of their sibling elements will be affected. Also, absolutely positioned elements do not extend their widths automatically. If width is not specified, they will only take as much space as the content needs.

The last type of positioning is fixed. It makes an element stay where it is when the window is scrolled.

A bug hunting session

I have been hunting down two strange bugs in my company’s projects since last week. We did a release last Friday and all cross-site login function stopped working. I popped in the office on Saturday to fix that up, but then another login method stopped working. That’s epic since they use exactly the same code to authenticate users. I sat down and looked into the code line by line, and finally located the prime evils.

The first one is the use of GetUser method of Membership class. Take a look at the following function signatures: Membership.GetUser(string) and Membership.GetUser(object). It’s easy to assume that the former should somehow invoke the latter internally. Yes, this assumption should be valid in most cases, but the GetUser method is an exception.

The official document for the overrides of Membership.GetUser reveals that when a string is passed as the parameter, it would be regarded as a user name, while object of any other types would be treated as user ID. This makes the difference quite obvious, as well as the cause of our problem. This is how we invoked the method:

var username = System.Web.Security.Membership.GetUser(userId.toString()).UserName;  

The intention was to get the current logged on user by ID, and get the user name. However, this line would always throw null reference exception because what we asked the system to do was actually looking up a user whose user name is the same as ID (a GUID), which is an extremely rare case, if any. The correct way to do this job is simply calling GetUser with a non-string parameter:

// userId is a nullable GUID
var user = System.Web.Security.Membership.GetUser(userId.Value);
var name = "";
if (user != null) {
  name = user.UserName;
}

Another prime evil was about URL en/decoding. I found that, in my company’s projects, the encoding results sometimes were different. For example, the equal character (“=”) was sometimes encoded to “%253d”, and sometimes “%3d”. That’s weird. I’m 100% sure that only the latter is correct, but how did the system get “%253d”? I looked up the URL encoding table, and found that “%25” is the percentage character (“%”). Ah, so the system must have encoded the piece twice.

So, next step is to find out where did this double encoding happen. After another hour or two, I located this line:

// From ExtensionMethods.AddQueryKey. values is a NameValueCollection returned
// from HttpUtility.ParseQueryString()
ub.Query = values.ToString();

That’s the root of problem although it disguised very well. The thing is that the return value of HttpUtility.ParseQueryString is not a simple NameValueCollection. It’s an instance of an internally used class called HttpValueCollection (from Reflector’s output), which inherits NameValueCollection and overrides some methods, and one of the extra work it does in ToString is to encode it according to RFC2396.

tl;dr: Never make assumptions on proprietary frameworks, always have official documents on hand, and sometimes simple reverse engineering tool can help a lot.

Detecting offline status

On this year’s Google Developer Day in Sydney, Eric Bidelman demostrated the way to detect offline status in HTML5 by checking the window.navigator.onLine property. In the demo, he disabled the wireless and cable connection of his laptop and the test page showed the correct status accordingly.

However, this function seems to be working on Chrome dev version only. In most other browsers, window.navigator.onLine lies to me. According to MDN, in Firefox and IE, it never returns false until the user manually changes the browser to offline mode. In Chrome and Safari, it should return false when the browser is not able to connect to a local area network, but it doesn’t (at least in stable version). Here’s a test page.

A quick search for solution to this buggy implementation leads me to Remy Sharp’s post or rant. He introduced a way to get correct offline status by overriding the getter of navigator.onLine property. The customized getter makes an asynchronous HTTP HEAD request to check the status. HEAD request ensures the minimal response payload, and since it has to be served through an active network, the result must reflect the actual network connection status.

This polyfill is almost perfect. The only problem that concerns me is performance. It seems that in some mobile browsers, such as Safari mobile version, the navigator.onLine property is correctly implemented. We can verify this by browsing the test page on an iPhone and toggle the airplane mode. On the other hand, the round trip time in cellular network is comparatively longer than wifi or cable network. So, on these devices, HEAD requests may appear a bit chunky for offline status detection.

A simple improvement is to do a browser sniffing before the HTTP request. If a known version of mobile browser with correct implementation of navigator.onLine is detected, native implementation could be a better option over the HEAD request polyfill.

On Google Developer Day 2011

For the first time, I attended the Google Developer Day in Sydney last week. It was a wonderful experience, except for the poor wireless network. Lots of energetic developers were there, and the sessions were quite informative.

The keynote started at 9am, where guys from Google demoed and announced a handful of “new” features on various Google platforms. On Android, they demoed the new “Ice Cream Sandwitch”. I was quite facinated with the “Android Beam”. It is a technology that lets people share information by touching devices back-to-back. This is cool, but actually, after a brief research, this technology, near field communication or NFC, has already been used since 2006. Well, hope Google can make more creative use of it.

Another notable announcement of the day was the Google+ page. It looks the same with Facebook page. People can put their personal or company information, share photoes, etc on the page. So, what is the most significant attraction? I guess it was the benefits on Google rankings. Google+ pages were quoted as “inbound/outbound traffic to a wellknown domain”.

After the keynote people started to shift around to different sessions. All attendees got a free T-shirt and a pouch of badges. We were encouraged to sell, barter, and exchange the badges with others to collect the whole set of five (or four…I didn’t bother), and the prize for those who got all of them was a HUGE stuffed android doll.

The most impressive session I attended was Eric Bidelman’s Bleeding Edge HTML5. I never knew the browser could be this powerful before. Here’s a list of takeaways from my note:

  1. Animations, or other scripts, could be stopped when the page is invisible so that CPU could get a chance to do more important computation on visible page. Keywords: visibilityChange, document.visibilityState;
  2. The connection status can be detected by checking the navigator.onLine event;
  3. Web Intent is a handy way to integrate third-party services;
  4. Full-screen API;
  5. HTML5 audio API (vendor prefixed) could be used to shedule playback, generate sound, and process audio.

These information gave developers enough space to explore. I also attended the Google Place API and OpenID session in the afternoon. The “zombie apocalypse” presentation for the Place API was funny :)

It’s a shame that the “VC” was not able to come to the VC panel, but I still heard opinions from lots of people who are running, or planning to run their own businesses. Most of questions from the audience hit the key points on starting businesses and funding, and the entrepreneurs on the stage were quite generous about their experiences.

To wrap up, it was a very informative and exiting one-day-trip. The knowledge and experiences I learnt in those sessions may take me several days to digest :)

Notes on CSS vertical centering

The vertical centering problem usually seems a bit confusing. I still remember that I tried very hard putting vertical-align: middle everywhere trying to achieve the expected layout. So today, I’d like to share some notes on vertical centering in CSS, and hope they can save you some time.

Firstly, let’s see what does this vertical-align do. You may find the definition on w3school.com as: “(it) sets the vertical alignment of an element”. If you believe this, the following example might shock you:


To be centered…

/* CSS */
.center {
    vertical-align: middle;
}

Yes, the element is not centered. Did the w3school lie to us? Well, I would say they just didn’t make it very clear. The reason why the element is not centered is that the vertical-align property only works on inline elements and table cells. When it’s applied to the correct elements, vertical-align will work as expected.

So, now the question becomes how to center block and text elements? Let’s work them out.

Centering a block element

As vertical-align doesn’t work on block elements, we need to manually position the elements:

<!-- HTML -->
<div class='container'>
    <div class='center'>To be centered</div>;
</div>

/* CSS */
.container {
    position: relative;
    height: 600px;
}

.center {
    position: absolute;
    top: 50%;
    margin-top: -240px;
    height: 480px;
}

Actually, this is just some simple math. The idea is to align the vertical median of both elements. We can achieve this by moving the center element down by half of the container’s height, and then up by half of its own height.

Centering text

Vertically centering text is much simpler than centering a block element. All you need to do is to set line-height to be the same as the container’s height. However, this only works for single line text. If you have a paragraph to center, you may still need to put them to a block element and apply the previous technique.

Vertical centering is an old topic. The techniques to center various elements have been discussed for a while. Although some of them look a bit hackish, I guess they’re probably the simplest ways to achieve this so far, and I do hope that the CSS working group can provide a consistent way to vertically center all elements in the future.

On iPhone 4S

I’m not good at evaluating products, but on hearing so many judgements out there about that iPhone4S has disappointed investors and long-term Apple fans, I was really annoyed. I’m not a big fan of Apple products, although I’ve used iPhone 3G for 3 years, nor a fan of Steve, but I really want to say something for Apple here.

So, iPhone4S. This product is somehow legendary, she’s born one day before the passing of her father, but let’s get out of this melancholy context for a moment, I don’t want it to influence my opinions either. This device came with dual core processor, a new OS, a set of integrated services, and small enhancements on other hardware as well. In a word, it’s improved. Not greatly enough for a jump in major version number, but enough for a minor one. If you think iPhone4 was a great device, why an enhanced version of it is not? That’s just ridiculous. Some people said they were disappointed about the new iPhone after a 15-month wait. I find this statement itself absurd. You started to wait for the next iPhone right from the moment you got an iPhone4?! I would just take these statements as bullshit unless the person could prove himself was a prophet.

But, where did all these disappointments come from, you may ask. Well, because of not meeting consumers’ expectation. Then, where did all those expectations come from? Let me tell you. All from those bloody rumors! Apple has NEVER said they gonna ship the next iPhone with LTE. They NEVER said they gonna use a larger touch screen. They NEVER said there would be a dramatically changed look. All those craps were credited to those rumormongers. They are not enthusiasts for technologies. They make money by spreading rumors! As a developer, I’m really annoyed about them. We have our own product release timeline and our own requirement spec for each iteration. These things were analyzed carefully before being settled down. We know what’s gonna be delivered in the next release, and we will make sure that the release would include enough features for a jump in major or minor version number. But those rumormongers don’t! They just tell what they think might be delivered, which is usually too illusory and utterly groundless. Unfortunately, lots of consumers take their words as official. They naively thought they got the first hand, unannounced details. They thought that they were pioneers. Now, everyone can see how wrong they were.

I also heard some people simply judge a product by hardware specs, and dismiss the new iPhone for not supporting LTE, not having a big screen, and etc. They also compare it with Android saying that all that is available on iPhone is available on Android, so stuck on iPhone is more out of a religious worship. Again, the statement itself leaks how naive the person is. Firstly, if you really wanted to compare something from Apple with Android, use iOS. Android is an mobile operating system, not a phone! Yes, it’s an amazing system too, and, as an addicted Google service user, I agree that the integration with all these services is very helpful. However, in terms of usability, I still find iOS outperform it. It has the most number of apps on it, and the least number of weird default settings. On Android devices, for example, I even get vibrate feedback by default when typing a text message! I’m not sure if this appears on all Android devices, but this setting really shocked me off. Go back to the hardware comparing, just ask yourself how much of those hardware would you use everyday if you could ever tell. Will you use a super computer to calculate your monthly expense? Be realistic my friend, mobile devices are for use, not for showing off the specs. Will your parents care how many CPUs their new phone has? Maybe not. But would they mind if they couldn’t play one of their favourite games any more on another device? You can tell the answer.

I think I made my points clear. I never expect my poor language could ever shut up those malicious commentators (if you know me, maybe you got the idea who I am talking about). I just want to tell people, please don’t judge a product by others’ words. You ain’t gonna use it for them.

Building an iOS-like jiggling icon with CSS3

When we tap and hold an app’s icon on iOS devices for a second or two, it starts to jiggle, expressing the fear of being deleted or moved. Let’s see how to mimic this effect with CSS3.

As usual, we start off by creating the markup for our icon:

<div id='app' class='clickable'></div>

And give it a basic look:

.clickable {
    cursor: pointer;
}

#app {
    background-image: url('http://dl.dropbox.com/u/13240406/images/ios-5-icon.png');
    -webkit-border-radius: 16px;
    -moz-border-radius: 16px;
    border-radius: 16px;
    height: 114px;
    width: 114px;
    margin: 0 auto;
}

We can even make it look more like real iOS app icon by adding a dummy badge. This can be done using the :after pseudo element:

#app:after { 
    background: -webkit-gradient(linear, left top, left bottom, from(#f08139), to(#b70815)); 
    background: -webkit-linear-gradient(left top, left bottom, from(#f08139), to(#b70815)); 
    background: -moz-linear-gradient(top, #f08139, #b70815); 
    border: 2px solid #fff; 
    -webkit-box-shadow: 0 0 3px #333; 
    -moz-box-shadow: 0 0 3px #333; 
    box-shadow: 0 0 3px #333; 
    -webkit-border-radius: 16px; 
    -moz-border-radius: 16px; 
    border-radius: 16px; 
    content: "1"; 
    color: #fff; 
    display: inline-block; 
    font-size: 22px; 
    height: 30px; 
    line-height: 30px; 
    min-width: 30px; 
    position: relative; 
    left: 82%; 
    top: -10px; 
    text-align: center; 
}  

Looks pretty neat. Now, it’s time to have the main course. The jiggling effect is implemented by a combination of CSS3 transform and animation. The idea is to play an infinite animation that slightly rotates the icon back and forth with a short interval:

.jiggly { 
    -webkit-animation: jiggle 0.2s infinite; 
    -moz-animation-duration: 0.2s; 
    -moz-animation-name: jiggle; 
    -moz-animation-iteration-count: infinite; 
    -webkit-transform: rotate(-1deg); 
    -moz-transform: rotate(-1deg); 
}

@-moz-keyframes jiggle {
    0% {
        -moz-transform: rotate(-1deg);
    }
    50% {
        -moz-transform: rotate(1deg);
    }
}

@-webkit-keyframes jiggle {
    0% {
        -webkit-transform: rotate(-1deg);
    }
    50% {
        -webkit-transform: rotate(1deg);
    }
}

The icon should be rotated counterclockwise by one degree to kick off the animation when the class is added.

If we apply the jiggly style to our icon now, it should start jiggling. But let’s make it look more like a native iOS app icon by adding a delete button. It should appear at the top left corner when the icon is jiggling and disappear when it stops:

.jiggly:before {
    background-color: #222;
    border: 2px solid #fff;
    -webkit-border-radius: 16px;
    -moz-border-radius: 16px;
    border-radius: 16px;
    -webkit-box-shadow: 0 0 3px #333;
    -moz-box-shadow: 0 0 3px #333;
    box-shadow: 0 0 3px #333;
    content: "x";
    color: #fff;
    display: inline-block;
    font-size: 26px;
    position: relative;
    left: -13%;
    top: -10px;
    width: 30px;
    height: 30px;
    line-height: 26px;
    text-align: center;
}

OK, almost there. We just need a function to toggle the animation. So, it’s time to bring in some JavaScript:

$('#app').click(function(e) {
    $(this).toggleClass('jiggly');
    return false;
});

$('body').click(function() {
    $('#app').removeClass('jiggly');
});

That’s it. a simple but interesting effect.

You can view the live demo here. Remember to use a browser that supports CSS animation, and feel free to fork it ;)

JavaScript proxy pattern

I spent this morning on reading the source code of Jasmine, a behaviour-driven development framework for JavaScript. I was quite interested in the spies, which intercepts a function call and alters the behaviour of it, and that eventually led me to a comprehensive study of the proxy pattern in JavaScript.

A proxy is a surrogate that implements the same interfaces as another object. It can be used in place of the real object and add additional behaviours. For example, proxies are usually used to log method invocation. They take method calls, log them, and pass on them to the real object that actually handles them.

Let’s see how does the canonical proxy pattern looks like in JavaScript. Firstly, we need an interface. In JavaScript, interfaces can be emulated in various ways. Here, we’ll do that with duck typing:

var Interface = function(methods) {
  this.methods = [];
  for(var i = 0, len = methods.length; i &lt; len; i++) {
      if(typeof methods[i] === 'string')
          this.methods.push(methods[i]);
  }
}

Interface.prototype.checkObject = function(obj) {
  for(var i = 0; i &lt; this.methods.length; i++) {
      var method = this.methods[i];
      if(!obj[method] || typeof obj[method] !== 'function')
          throw 'Interface not implemented';
  }
}

This is a naive implementation. Every interface maintains a list of function names that need to be implemented, and a helper function to check if an object did so. We don’t have to declare an object to implement an interface, but when we want to use functions defined in that interface, we need to check the conformity explicitly.

With that, we can build a simple proof-of-concept proxy factory:

function createProxy(obj, intf) {
  var proxy = {};

  // Check if the object actually implements the interface
  intf.checkObject(obj);        

  // Add additional behaviour to the base functions
  for(var i = 0, len = intf.methods.length; i &lt; len; i++) {
      var method_ = intf.methods[i];
      proxy[method_] = function() {
          console.log('Proxy is called');
          // Delegate actual method invocations to the real object
          return obj[method_].apply(this, arguments);
      }
  }
  return proxy;
}

The returned object is a proxy that “implements” all functions in the specified interface. It passes on the actual method invocations to the real object. In this way, the proxy can be used in place of the real object wherever the functions defined in the interface are used:

var Subject = function() {}
Subject.prototype = {
  'echo': function(arg) {
      console.log(arg);
  }
}

var foo = new Interface(['foo']);
var sub = new Subject();
var proxy = createProxy(sub, foo);
proxy.echo('bar');

That’s a direct port of the proxy pattern from other object-oriented languages. It is implemented based on the canonical proxy pattern introduced by GoF. However, this method requires us to create interfaces to use proxies. That may be useful when we have a number of functions to wrap up, but it is really annoying if we just want to add some extra behaviours to a single method or multiple methods in totally unrelated objects. For example, suppose we want to add logging support to draw() in square class and eat() in animal, it doesn’t make sense to create interfaces for draw() and eat(), and force the square class to implement eat().

Let’s try to get rid of interfaces, and build a function to add proxy for arbitrary methods:

function setLoggingProxy(obj, methodName) {
  var proxy_ = function() {
      console.log("Method '" + methodName + "' is being called.");
      return proxy_.originalMethod.apply(this, arguments);
  }
  proxy_.originalMethod = obj[methodName];
  obj[methodName] = proxy_;
}

var sub = new Subject();
setLoggingProxy(sub, 'echo');
sub.echo('foo');

Now, we don’t even need an explicit proxy object. Nifty :)

Actually, this interface-free paradigm is how Jasmine spies are implemented. The spyOn method calls the proxy factory that returns a spy object with initial state. Then we specify extra behaviours by calling andCallThrough, andReturn, and so on.

The use of “!!” in JavaScript

So, double exclamation. I came across this combined operator when studying the Modernizr source code. At first glance, it’s just an unary operator that takes the boolean representation of a value and invert it twice. That’s not quite exciting, but with an understanding of falsy values in JavaScript, there are some interesting uses of this combined operator (it’s just two ! operators being put together).

The first use is more towards JavaScript beginners. It helps to check if a value is interpreted as true of false. For example, is an empty string represents true? We can simply do:

console.log(!!""); // false

and what about an empty array?

console.log(!![]); // true

So, every time when you’re not quite sure about whether a value is truthy or falsy, this operator can be an easy way to verify. I’m not in favor of people considering it as a type conversion operator. It’s obscure, and the result can surprise you.

”!!” also provides a lightweight approach to help checking existence of an object without revealing the internal structure. Let’s take a look at a snippet from the Modernizr source code:

tests['applicationcache'] = function() {
    return !!window.applicationCache;
};

This function simply tells if applicationCache is available. If it’s not, window.applicationCache will return undefined, which is falsy. This is a recommended approach to check existence. It keeps the function simple and testable, and does not reveal any additional information (see the YAGNI principle).