Making the Most of Silverlight Text Rendering
Plenty of people (myself included) have had some less than favorable things to say about text rendering in WPF and Silverlight. Well haters gonna h8, but we’ve come a long way! Here’s thet thing: text rendering is not only hard but it’s highly subject. That’s why a tool like photoshop makes you choose a rendering method (one of 5) for every text element on the canvas. There really isn’t a single rendering methodology that is going to look great for all fonts in all situations.
If you think about it, you’re dealing with the intersection of a lot of variables: the glyphs in the font itself (is it thin, thick, etc.), the features of the font (whether it supports hinting, etc.), the size of the font and the context in which it is used (the color of the text, the color of the background, etc.).
The fancypants engineering that turns all of that into pixels on a screen is not going to get it right all the time, especially for something like type where our eyes are highly trained and people (designers and non-designers alike) have strong opinions.
So, in that spirit, I thought I’d share some of my (highly subjective) opinions. Here are a couple of things that I do get better text rendering in Silverlight:
1. Choose Good Fonts at the Right Size
Some fonts just seem to be made for Silverlight and some feel like a fight. Unfortunately, there are no rules about this. It takes a little trial and error. And to make it even more complicated, the results are pretty dramatic depending on the size at which you’re rendering. The same font might look pretty good at 12px and crummy at 13px.
Segoe and Verdana both look okay at display sizes. I prefer Verdana at 11px or 12px. Segoe works great at 14px but kind of looks awful at 11px (especially bold).
Confusing? Unfortunately, it sort of is. The good news is that for display font sizes (10-14px or so), you’re generally better off sticking with what you know anyway. At that size, you shouldn’t be trying to be creative or really even establish a mood. You should probably be focused on conveying information. To that end, a common font is an asset because it lets the text itself have the voice instead of the font its written in.
For larger sizes, you may want to be a little more expressive and there you’ll have to do some digging. Keep that in mind as you design or work with your designers to that they understand: when it comes to production, you may have to tweak font sizes by a pixel or two here and there to find a match to the Silverlight text rendering engine.
Seems a little arbitrary, right? Why should the same font look so different (jaggy vs not, etc.) at two very similar sizes? It’s because of text hinting and that brings us to…
2. Understand Hinting (and turn it off some times)
Text hinting (or font hinting) is like pixel snapping for fonts. It’s a way for the font author to specify the “critical” lines in each of the glyphs, the ones that need to land on pixel boundaries. The result of well hinted text is that the stems in a letter like “M” fall on pixel boundaries and you get text that looks much crisper.
Microsoft tends to be pretty aggressive when it comes to text hinting and that typically accounts for the difference in font rendering between Windows and Mac. Strongly hinted text feels crisper but a little bit more jaggy. At large sizes, text hinting doesn’t matter and in WPF and Silverlight, you can usually find the “magic” size where the rendering algorithm stops paying attention to hints. For Segoe UI (in WPF) this happens somewhere between 20 and 21px. You can see the difference below:
This is how text hinting accounts for the big differences between seemingly small sizes. It’s not just because hinting switches off at certain sizes, it’s also the fact that as you move from size to size, you’re doing a bunch of rounding. You’re literally changing the underlying glyphs that make up the characters in the font so that they align to pixel boundaries.
This also explains why you get a lot of artifacts in the “medium” sized display sizes (13px through 20px or so): at smaller sizes, hinting does less because many of the glyphs end up being a single pixel wide (think of the letter I at 10, 11 or 12px—there’s a good chance that it will only be a single pixel wide at any of those sizes). When you move up just a little, you still have hinting in the math, but now the difference is more noticable and as you move from, say a 17px font to an 18px font you may actually see a significant change in the shape of a glyph. This effect sets in even earlier for bold text.
You can probably already feel my bias here. At small sizes, I really like hinted text but for medium sizes, I think it distorts the glyphs and generally looks too crisp. In my opinion, this is why people complain about Silverlight and WPF text rendering. It’s too aggressive in it’s approach to hinting. I won’t pretend to be an expert, but I’ve heard that this has something to do with something called a gamma table. I mention that only because it sounds awesome.
Earlier I said that Photoshop lets us choose between 5 different mathemagical formulas to get pretty precise control of text appearance. Well, Silverlight isn’t quite that generous, but there’s one huge switch that we can throw: TextHintingMode. Hooray!
When you set TextOptions.TextHintingMode=”Animated” you are essentially telling the rendering engine to ignore hinting. Thanks! I think it’s called “Animated” because if you’re text is animated, you presumably don’t care about how it lines up against pixel boundaries anymore.
Basically, when you set TextHintingMode=”Animated, you tell Silverlight to render your text using the same algorithm it uses at larger sizes, the one that ignores hinting. The result can be that the text feels a little fuzzy at smaller sizes, but I think it often looks much better. Here are a couple of examples:
You might prefer the hinted text (Fixed above). From a technical perspective, you could probably make an argument that it’s more “correct.” It’s definitely brighter and I think that some people would argue that’s more readable because of that.
On the other hand, I think anyone would agree that the “shape” of the letters in the “Fixed” text is a little distorted compared to the “Animated” text. Look at the top sample. That’s Verdana. Checkout the top of the “6” in 16 for the bold version of that font. It’s been reduced to a single horizontal line. The same goes for the top and bottom lines in th
e little “z” in size. If you compare those to the non-hinted version, it’s clear that those lines should all have a little more weight to them.
The result of all of this is that I use TextHintingMode=”Animated” a lot. A whole lot. In fact, this property inherits and I usually just set at the top of the app and then “opt out” instead of opting in. If that makes things look fuzzy, um, sorry. I like it.
15 Comments
Derek Lakin / JUL 08 2010
Great post, Robby, thanks!
I think some of us mere mortals could probably do with a cheat sheet to help us out, but as you say, it’s subjective, so we probably each need to do our own :P
Christopher Bennage / JUL 08 2010
Totally righteous. I’ve been struggling with font clarity and trying to better understand the problem. I was aware of the TextHintingMode, but I didn’t grasp the implications. This was very helpful.
Joe / JUL 08 2010
Excellent writeup :)
John Bergdahl / JUL 08 2010
Thank you so much!
I’ve had lots of problems with text rendering in Silverlight, and I have said many unfavourable things about it. But I didn’t even know about text hinting mode until I read your post just now. I tried it out on one of my apps, and it looks a lot better. At least according to my subjective opinion. :)
Robby Ingebretsen / JUL 08 2010
@Derek. Great idea about a cheat sheet. I’ll do it.
@Christopher, Joe. Thanks guys.
@John. This post actually grew out of a tweet yesterday where I said that I wish TextOptions.TextHintingMode=”Animated” were the default! I wish that because think that a lot of people don’t realize that you have control over it and so they stick with the default…and well, you know my preference :).
Sean Rooney / JUL 09 2010
great post, and i would say applicable even to people not coding in silverlight or wpf. I’ll recommend it to everyone i know who’s having font difficulties, which is everyone i know who codes :)
and I agree – “gamma table” sounds awesomely nerd-tastic
DotNetShoutout / JUL 09 2010
Making the Most of Silverlight Text Rendering…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
Random Reading – F#, Azure, PDC, MSBuild and More « Tales from a Trading Desk / JUL 14 2010
[...] Making the Most of Silverlight Text Rendering [...]
Al / JUL 15 2010
Excellent post! Everything is spot on from my experience. I have spent quite a bit of time tweaking my “Animated” fonts to get just the right appearance. It is crazy that the tiniest change (10.05 vs. 10) can sometimes make a huge difference. I have also found that font color and weight can really improve readability.
richard@estringsoftware.com / AUG 05 2010
Nice post thx – does the majick size depend on your currently selected screen rez? I.e. if you find that perfect look is it likely to still come out different on different monitors?
KC / SEP 02 2010
This is an amazing tip! Thanks a bunch for sharing Robby :)
slyi / SEP 08 2010
I find MS Gothic at 10.666 and 14.666 look near perfect, i think it relates to the bitmap font support http://blogs.msdn.com/b/text/archive/2009/08/24/wpf-4-0-text-stack-improvements.aspx
Links (10/25/2010) « Everything SharePoint/Silverlight / OCT 25 2010
[...] Making the Most of Silverlight Text Rendering [...]
Ryan / FEB 17 2011
I had read this post a few months ago and bookmarked it with good intentions. I just applied this to a site that I’ve had up for awhile, and wow, just WOW! The font looks so much smoother and more elegant. It is amazing how the subtlest of changes can make such a huge difference. Thanks for the great post.
nerdplusart.com / FEB 28 2011
[...] high fidelity visuals in XAML: UseLayoutRounding (like SnapsToDevicePixels but more reliable) and TextOptions.TextHintingMode which lets you specify whether or not to rendering your text with hinting (a small property with [...]