< /troll >

Two years ago, I started my first job at Nokia, Qt Development Frameworks. Originally planned to become a Mac developer, I ended up working on the text layout and font rendering part of Qt. Not exactly carried out what I wanted to do, it is still a fantastic job with many good memories. Some of my favorite parts of this job are:

  • Passionate co-workers with the amount of dedication I have never seen before. I really enjoyed working with the fellows in graphics team. Many of them have spent more than ten or even twenty years on graphics programming. It is truly a team I’m honored to work with and I learnt a lot from them.
  • Really high quality code base with decent workflow (git and gerrit are the best tools and JIRA for bug tracking worked well for me).
  • Nice office layout with separated rooms.
  • Social activities such as climbing, skiing and movie nights, we also helped each other on moving and hang out together in house warming parties – time spent with friendly and helpful trolls is one of my best memories.
  • Free drinks and snacks (I enjoyed the apple juice, chocolate milk and cookies).
  • Ice creams for the whole summer, and donuts on the first Friday of every month.
  • Lønningspils – a Norwegian tradition: monthly beer drinking on paycheck weekends.
  • Table tennis – I guess I let a lot of people down as a Chinese yet played just so so in this sport.
  • The 8-core Mac Pro I used as the main development machine.

Things that didn’t work that well includes:

  • Pressure from Nokia to do some of the stuff I didn’t enjoy that much and ended up not shipping anything, I surely learnt a lot from it, but still felt that is a waste of time.
  • Canteen – It was quite good when I joined, but got much worse from the end of last year when the previous chef left. Terrible soup choices and warm food usually tasted awful.

Anyway, after these wonderful two years, I think it’s time to move on. I want to work on something else now. So I didn’t join most of my colleagues transferring to Digia, but I sincerely think that they have a very good chance of succeed and making “Qt Everywhere” more true than it is. It has been a great ride and if anyone is looking for a job and Digia is hiring, I can recommend it without any hesitation.

I will try to cover what’s next for me in the next post, stay tuned 😉

Thoughts on Learnable Programming

After reading Bret Victor’s new essay Learnable Programming and some of the responses, the idea keep lingering in my head.

While his famous lecture Inventing on Principle tackled the idea of making new principles, people are mostly interested in applying that visualization method on IDEs and such. Although most of these efforts are largely experimental, I still find it harsh to dismiss them and consider them as a failure. Live coding is not the point of Victor’s lecture or essay, but it is still immensely better than a dumb editor and cold console that I used to use to learn programming.

(My girlfriend, who majored in landscape design, learned most JavaScript concepts with the rudimentary web editor from Codecademy. She found it engaging and helpful. I doubt she will find it that way if she was given a Unix console and gcc, checking a.out output every time a change was made.)

In the area of learning a new way of thinking, things as simple as live coding can be useful.

What’s more important is how do we progress after grasping basic concepts like iteration and function? While most people think learning programming as a one time effort, I have programmed for more than 10 years and I’m still constantly learning.

Malcolm Gladwell’s Outliers brought us the concept of 10,000 hours of practice. He told us that Bill Joy became a master after practicing programming for 10,000 hours. But what exactly has Bill Joy done in his practice is unknown to us. We all knew that Bill has coded the vi editor and some of the BSD network stack. Did he start practicing from writing a smaller subset of vi or BSD?

The essential question here is how do we learn higher levels of abstraction and design systems more complicated.

First, I personally believe that we need to understand the details to do higher level designs. You won’t be able to design an efficient system without knowing the implementation costs and performance impact of critical code paths. That’s why I usually choose to dive to the bottom and solve/evaluate a few critical issues before looking at the big picture.

However, human mind is not a precise machine that can assemble low level details into high level constructs. After mastering the details sometimes we need to take it away, clear our minds to see a bigger picture, otherwise our heads will be occupied by low level details and have no time to abstract. Contradicted as it is, visualization becomes a really useful tool to hide the details for us.

With visualization as simple as a pie chart, we will suddenly able to free our minds, stand on our previous results and reach higher fruits. That, I think, is the real value of Bret Victor’s idea. What I disagree with him is that his idea doesn’t have to be a groundbreaking rule to revolutionize our ways of programming, the existing tools and IDEs can still equip that as a weapon, to help us tackle even more complex problems.

Imagine code visualization as an amplifier. Without that it is possible to work on certain issues, but with that you are suddenly able to work on harder issues in a more efficient manner.

How to make that really work? Let’s start from small. Take your favorite IDE for example, Xcode can have built-in visualizer for native Cocoa classes such as NSString, NSArray, NSColor and NSFont. The code to show them is already there, just need to find a way to present. Qt Creator can have visualizer for QString, QTransform, QColor and QFont, etc.

For visualizing the states of a program, it works just like our existing debugger with variable watching feature. Except that is presented in a structural way, specific presentation can be given by the programmer himself, just like writing a test case. We can have a drag-and-drop layout interface to do that.

Some of Bret Victor’s ideas (like parameter tagging) can already be achieved with a static analyzer such as clang. Others can only be done in execution. How to speed up execution to avoid setting up a lot of states is the most interesting problem. I think we can try to reduce the amount of input and take an independent block of code (functions without side effects) for examination in an isolated sandbox environment, supplying the required parameters in a simpler way just like preparing for test data sets.

In summary, I still expect that this visualization tool as a programming assistant. An assistant that can take a piece of code, walk through its execution and explain it to me how it works. Even if can only tell how does one variable transits in a loop, it will still be much better than me evaluating it by hand with paper and pencil. In short, hand the repeating tasks over to your machine and focus on something more creative, that’s what we humans are good at.

Tools for a typography hacker

一直想写篇 blog 介绍一下常用的、跟字体技术相关的开发调试工具,我一般用 Mac OS X 或者 Linux 开发,所以工具也集中在这两个平台下,也有的是跨平台的。这里只说我自己常用的,欢迎补充。

  • UnicodeChecker

    Mac OS X 下完美的 Unicode 字符查看工具,可以根据 UTF-16 编码 (10 进制、10 进制)、UTF-8 编码来查找,或者直接复制粘贴字符进去,可以选择不同的字体查看该字符对应的字形,包含完整的 Unicode 字符属性数据库,可以自动下载安装 Unihan 数据库。几乎是每次开发和调试问题的必备。Linux 下有 gucharmap 实现类似的功能,但要弱很多。

  • ttx

    将 TrueType/OpenType 文件按照指定的表 dump 成 XML 格式,或者反过来,所以既可以查看也可以修改。非常方便分析 OpenType 的 GPOS/GSUB 特性查找表。这是一个命令行工具。更简单一点的 TTF/OTF 分析命令行工具还有 lcdftypetools 里的 otfinfo,可以直接列出字体的特性,但没有细节显示。

  • FontForge

    大部分 TTX 的功能也都可以用 FontForge 实现,虽然界面是基于 Xlib 的相对老旧,但它的功能实在是强大,不过我一般也就用来编辑字体的 name table 和 OpenType feature。

  • hb-view

    harfbuzz-ng 提供的工具,可以用指定的字体、指定的 OpenType 特性,将 HarfBuzz 排版好的内容以 FreeType 渲染出来,方便对比测试特性字符串的布局正确性。当然,通常我还会用常见的浏览器、文本编辑器等来比较,尤其现在 Firefox 和 IE10 TestDrive 支持 OpenType 特性指定了,测试起来就更方便。

  • fc-list, fc-match

    fontconfig 提供的工具,主要用来分析 Linux 下的字体匹配,在阅读它的用户文档之后,善用 -v 和 -a 参数,可以直接获得不少字体的信息。

  • Pixie

    Xcode 自带的屏幕放大镜,用来分析 subpixel antialiasing 非常给力。别的平台下当然也有类似的工具,比如我在 Linux 下用 KDE 的 kmag。

  • The Font Game, Kerning Game 和 letter shaping game

    三个制作非常精良的字体相关小游戏,第一个是 iOS 上的字体辨识,后两个则是体验对间距形状把握的 HTML5 在线游戏,适合在开发之余放松一下大脑 😉

Qt 的文本渲染技术

Qt 的文本渲染技术

去年 12 月中在北京的 Qt 开发者大会上,我做了一个关于 Qt 的文本渲染技术的讲座,兼谈及了一些文本渲染的基本概念和过程,和四年前在清华 thossclub 讲的《文本渲染技术的一次短途旅行》相似但又有些新的内容,有兴趣的朋友可以看 slides,等有录像视频时我也会加上链接。

Is Cocoa a legacy framework?

Kyle Neath wrote an excellent piece about the design process of GitHub for Mac. What’s more interesting is his concern about the Mac OS X/Cocoa framework as a whole, it’s the best criticize of Cocoa that I’ve seen for a while, I sincerely recommend any developer interested in Cocoa to read.

According to Kyle, a first-time Mac OS X designer/developer, Cocoa is dying for a framework. This argument feels a bit ironic since I came from the age when a bunch of Cocoa fanboys were labeled as the “Delicious Generation” who only wrote fancy good looking apps with no actual functionalities, while the good ‘ol Carbon guys looked so damn unattractive. Has it now come to the downfall of us Cocoa developers?1

Kyle’s main reasons for not liking Cocoa are as follows:

  1. Drawing in code is slow and painful. Images are easier to work with and result in more performant code.
  2. There is no layout engine for Cocoa. If you want two elements to rest side to side, you’ll need to calculate the pixel size of the text, padding, borders, margins — then manually position the next element.
  3. There is no styling engine in Cocoa. (To change the background color of a button for instance will require significant changes)
  4. Learning the differences between layer-backed views, layer-hosted views — understanding that you have to subclass everything — balancing delegates, weak connections, strong connections, KVC, view controllers, and notifications — understanding little intricacies like how AppKit flips .xibs when it load them up or how hard it is to make one word in a sentence bold.

I will try to share some of my opinions about them, one by one.

Is draw in code slow and painful?

Being a low level graphics developer for so long, I know my opinion must be biased. But still, I’ve never felt drawing in Cocoa (or Cocoa Touch) to be slow, working with Core Graphics, Cocoa Drawing API and APIs like Core Text is quite pleasant actually. Drawing operations are always blazingly fast. I honestly couldn’t see a better way to solve these problems without resorting to low level. Yes, they are imperative APIs rather than declarative, yes, you have to do your -drawRect: code cautiously. But low level drawing itself has never been a bottleneck for my programs. The real problems are scheduling what to draw and finding out when stuff is drawn.

So in my opinion, it’s not the drawing itself that’s slow and painful, but you need to have a thorough understanding of the graphics stack to be able to write efficient low level imperative drawing code. That’s a damn steep learning curve. That’s why very few people can write efficient yet complex drawing code even veterans like Loren Brichter recommend to “do your own drawing”.

However, there is no silver bullet. Cocoa Touch makes life a little bit easier by simplifying the view hierarchy and build with Core Animation from ground up. But to have butter smooth scrolling, you still need to do your own drawing cautiously. Apple did provide layer-based and layer-hosted views in Cocoa, but they are too conservative to re-architect the entire Cocoa view stack with Core Animation, that’s a pity but luckily you can always roll your own (as we always did).

Anyway, the best framework I can imagine is the one using a declarative API to construct most of the UI and leverage the full power of GPU, with flexibility to do custom drawing with an imperative API.

No layout engine for Cocoa?

Apparently, Apple is solving this with Cocoa Autolayout. Can’t say much about this (it’s in NDA) but it does look promising.

No styling engine in Cocoa?

Well well, this is controversial. On one hand people are complaining that UI in Mac OS X apps are not consistent anymore, on the other hand people detest Aqua and dream for change from the bottom of their heart. I can understand Kyle since he is more of a designer than a developer. With no doubt I think that’s a fair judgement, but it’s hard to justify whether the styling difficulty contributes to HIG consistency or drives people to the opposite side of it. As a user of Mac OS X I felt that UIs should be “semi-consistent”, or as John Gruber puts it eloquently: uniformity has been replaced by conformity.

Apple is acting slow and they can definitely improve on this. The solution doesn’t have to be very innovative, adding styling flexibilities here and there is no groundbreaking change. Cocoa Touch is not far superior either, there is still a lot of work to do if you don’t like the standard controls from UIKit. In contrast, my biased opinion would say that QML/Qt Quick appears to be a much more flexible solution, it’s XUL/Air/JavaFX/WPF done right. Though I am biased, who knows me well should know that I’m hard to convince as a low level graphics engineer.

Cocoa has complicated intricacies?

Yes, any framework survived more than 20 years will have some intricacies, that’s inevitable. Actually I’m surprised by the fact that so many of the NeXTSTEP APIs are still in good use. Come on, it’s a fast changing industry and you really need to be a genius to predict the trend in more than 10 years.

However, most of Kyle’s concerns came from his expectations: he expects to fit UIKit model as is into Cocoa but it didn’t work. It probably never will, as I said previously, Apple is conservative in that sense, for stable platform like Mac OS X, they tend to provide new options other than forcing everyone to adapt to the new model. That inherently complicates the framework, of course. Changes that us Cocoa developers applauded for can be seen as too cautious by iOS developers.

Anyway, I think it’s fair to say that Cocoa isn’t the best API for modern, dynamic UI, alternatives like Chameleon may eventually surpass it. Nevertheless, there is no easy path between both worlds, you either port the code to the new model (UIKit like) or adapt to the hybrid model (Cocoa like). For iOS developers, the former is definitely easier, but for us the latter seems to be a better option.

That’s it. I’m surprised that you can read my ramblings to this far 🙂

  1. I’ve never labeled myself as part of the “Delicious Generation”, I will rather do something useful if it can’t be good looking at the same time. But still, it’s sad.