基于 Mac 的媒体中心

iOS 4.3 新增的一个重要的功能是对 home sharing 的支持,这样你可以在一台安装了 iTunes 的机器上共享任何视频和音频而不需要同步到对应的 iDevice 中。这给打造基于 Mac 的家庭媒体中心带来了很大的便利。先前介绍过用 XBMC 构建媒体库的方法,安装了 XBMC 的 Mac mini 是我目前主要使用的视频播放设备,自从 Mac OS X 开放了视频硬件解码支持 之后,用低配置的 Mac mini 播放高码率的 1080p 视频也完全不是问题了。而且对于 iPad 2 和 iPhone 4S 以后的设备,因为已经支持到 H.264 的 High Profile 4.1,所以正常情况下,网上所有能下载到的 MKV 封装的视频,都只需要重新封装一下就可以无损地播放了。这里介绍一下我的配置。 Continue reading “基于 Mac 的媒体中心”

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 Gameletter shaping game

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

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. 

Apple 27″ LED Cinema Display 使用感受

ָApple 早在 7 月份的时候就随新的 iMac 和 Mac Pro 一起公布了新的 27″ LED Cinema Display,同时将原有的 24″ LED Cinema Display 降价、停产,而因为迟迟没有替代仍然一直在产的 30″ Cinema Display 也宣布销完存货不再生产,可是新的 27″ LCD 要到 9 月才可以订购,而从订购到送货在欧洲这个犄角旮旯又得等上一个月,所以直到 10 月中旬我才用上这款显示器。

技术上的评测在 anandtech 上已经非常详尽,这里不加赘述,关心技术参数比较的可以看那篇评测,这里只讲一点作为普通使用者的感受。

这款显示器的重量是 10.7 KG,接近一台 27″ iMac 的重量了,绝对不算轻,但相比以前的 Apple Display 显得薄了不少,尤其是相比 30″ ACD 所占桌面空间大为减少,我用的是一张 120x70cm 的桌子,感觉桌上放下两个这样的显示器仍然不会觉得太挤。

如同往常一样,27″ LCD 的设计非常简洁,没有外置的电源适配器,只需要从背后接一条线即可,支架设计了一个圆孔可以把线从中穿过方便整理,但支架只能调整上下角度,无法调整高度和旋转。接口也非常简洁,只有三个 USB 2.0 接口,三条连接 Mac 的接线分别是 Magsafe、Mini DisplayPort 和 USB。其中 Magsafe 可以直接给 Mac 笔记本提供电源——这几乎是 Apple 显示器唯一的“绝活”了。USB 用于同时提供与机器的数据传输和不支持 Mini DisplayPort Audio 机型的音频输出。

可是 27″ 版本的 USB 输出存在问题,表现是有时在机器休眠恢复之后就无法向显示器输出音频,音量调节 HUD 出现缓慢,Console 中也会输出一些错误信息,这个问题似乎不是硬件问题,但非常普遍,包括我在内的很多用户都遇到了,可以参见 Apple discussion 和 <a href="http://forums viagra au pharmacie maroc.macrumors.com/showthread.php?t=1027419″>macrumors 上的讨论,目前只有断开显示器电源重新接上,或者重置 SMC 两种解决方案,但效果都是临时的而非永久的。

因为是家里的环境,所以可以自己选择灯光,镜面屏幕在我这里并没有造成多大的困扰。如果觉得实在没法忍受镜面屏幕的当然 Dell 的 U2711 会是非常好的替代。因为工作性质的缘故,我不觉得在色域 (gamut) 上的缺乏对我有什么影响,但色彩的感受与我的 MacBook Pro 屏幕非常接近,这样就不需要自己调整显示器了。在有了 2560×1440 像素之后,全屏观看 720p 的 H.264 视频开始显得有点模糊了,而之前都很难看出和 1080p 的区别。

除了前面提到的问题,音频的效果其实是不错的,相比 MacBook Pro 的内置扬声器提升明显,虽然肯定不能和昂贵的音响系统比,但在桌面空间紧张,不想放多余杂物的情况下,这台显示器的扬声器效果足够令人满意了。

我之前主要的顾虑是接口实在太少,相比 Dell U2711 的所有接口都全 (DVI, HDMI, DisplayPort, VGA, Component),只有 Mini DisplayPort 实在不方便连接其他的设备,但后来考虑到手头其他设备的接口也只有 HDMI 一种了,用投影足够处理,而笔记本的 Mini DisplayPort 输出要转到 U2711 上却需要用到 Mini DisplayPort 到 Dual-link DVI 或者 DisplayPort 的转接,也稍嫌麻烦。如果实在需要把 HDMI 输出转接到 Mini DisplayPort 上,也可以用 Kanex XD

阅读器的进度显示与估计

对电子书阅读器来说,提示当前阅读进度是一项很自然的功能,习惯用电脑的人都常看到进度条 (progress bar) 和滚动条 (scroll bar),如右图是 Textus 中使用的右侧滚动条。

然而在实际实现中,进度计算是一件伤脑筋的事情,比如 Textus 的实现其实很简单:在打开文件时读入整个文件,然后整个交给 Core Text 去排版,将排版后的结果分解为行 (CTLineRef) 记录下来,并将所有行总的高度设置为整个文本视图的高度,这样,每当滚动视图 (NSScrollView) 移动到某个位置时,重绘函数 (-drawRect:) 被调用到,我们根据该位置来判断应该绘制从第几行到第几行的内容,再调用 Core Text 把这些行画出来。

这么做看似很简单直接,结果也很容易保证正确,带来的问题是,每次用户修改设置 (比如调整字体大小、窗口尺寸) 时,就得把整个文件重新排版一遍,即使此时我们只需要看到当前一页的内容。为什么这种方法这么低效,我还一直使用它呢?因为这个实现严格依赖滚动视图给出的位置来判断当前阅读进度,所以总的高度估计必须非常精确,不然随便滚动一下就可能出现错位,而一次算给出整个高度的方法最准确,不容易出错。

Continue reading “阅读器的进度显示与估计”