State of The Art Web Typography

We have reached the state that Web typography can be **much** better than it used to be. What kind of tools is in our hands?

* [Hyphenator](http://code.google.com/p/hyphenator/), with this JavaScript hyphenation support, reading justified text on your browser will no longer be a pain.
* [Knuth and Plass Line Breaking](http://www.bramstein.com/projects/typeset/) in JavaScript, combining this and Hyphenator then you will get beautiful typesetting like [this sample](http://www.bramstein.com/projects/typeset/flatland/).
* [optimizeLegibility](http://www.aestheticallyloyal.com/public/optimize-legibility/), CSS rule `text-rendering: optimizeLegibility;` will turn on cross browser kerning-pairs & ligatures, which is also critical for good typography. It does have some drawbacks though.
* Web fonts solutions like [TypeKit](http://typekit.com/) and high quality free web fonts from websites like [Font Squirrel](http://www.fontsquirrel.com/), provided much more vivid user experience than standard web fonts like Verdana and Georgia, but they should be chosen very carefully, otherwise the results can be much worse.
* [-moz-font-feature-settings](https://developer.mozilla.org/en/CSS/-moz-font-feature-settings), this feature, although it’s Firefox 4 only, can be very fun to experiment with, since it opens an [entire new world](http://hacks.mozilla.org/2009/10/font-control-for-designers/) of rich OpenType typography to the web. Combining this with web fonts solutions can make it even more useful.
* [-webkit-font-smoothing](http://maxvoltar.com/archive/-webkit-font-smoothing), when used in a clever way, can improve legibility (and some designers prefer grayscale antialiasing to subpixel antialiasing, that’s why it’s so popular nowadays). Unfortunately there are many existing websites abusing this CSS rule, including [Apple](http://www.apple.com) and [Twitter](http://www.twitter.com). In general, I suggest leaving it alone unless it’s absolutely necessary.
* [SmartyPants](http://daringfireball.net/projects/smartypants/) will convert ugly quotes, dashes and consecutive dots into beautiful punctuations that you really meant to use. It saves a lot of editing efforts.
* [MathJax](http://www.mathjax.org/), the only weakness of web typography comparing to [TeX](http://en.wikipedia.org/wiki/TeX) is math equations, MathJax is so good that it totally eliminated this weakness.

Think about it: what if we create an automatic web typesetting tool, combining all these efforts, how beautiful the result we will get? That’s what I am trying to do recently.

iPad 上新闻类软件的字体选用

上次在 twitter 上和 Typeisbeautiful 的 Rex 提到这件事情,最近刚收到 iPad,就来分析一下。

iPad 上的新闻类软件非常多,多到 app store 上有个 News 分类专门给这类软件,但良莠不齐也是自然的,但从字体选用看,我认为做得最有诚意的还是三个传统媒体:New York TimesNYT Editors’ Choice, WSJThe Wall Street JournalFinancial TimesFinancial Times iPad Edition。它们共同的特点是,为了优化阅读体验,都使用了专门订制的字体,随 app 一起提供,几乎完美地保持了纸面版本的字体风格。

Continue reading “iPad 上新闻类软件的字体选用”

阅读器的进度显示与估计


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

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

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

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

TeX Live 2009 的 LaTeX 中文支持

最近刚发布的 [TeX Live 2009](http://www.tug.org/texlive/) 是对中文支持有较大改进的一个版本,这里简单介绍一下。

首先,一如 2007, 2008 版本,TeX Live 2009 有中文版本的[安装使用指南](http://www.tug.org/texlive/doc/texlive-zh-cn/texlive-zh-cn.pdf),强烈建议在提问前把相关章节好好看看,这份指南主要叙述的是和中文无关的一些通用的问题。

然后 TeX Live 2009 的中文支持主要分为两部分,基于 XeTeX 的,和基于传统 CJK 宏包的。(我这里只讨论 LaTeX 的,如果你希望尝试 ConTeXt 和 luatex,可以参考 Li Yanrui 的 [blog](http://liyanrui.is-programmer.com/),他有很详细的介绍。)

#### 基于 XeTeX 的方案

这是我们推荐的方案,又可分为高层与低层两种,分别适用于不同需求的用户。

首先,安装所需的宏包:

sudo tlmgr install xecjk ctex

高层的方案是使用 ctex 宏包自带的文档类,例如原来用 article 文档类的就改用 ctexart 文档类,原来用 book 文档类的就改用 ctexbook 文档类,这样绝大部分你会遇到的中文问题,比如字体设置、hyperref 的调用、章节标题的设置等等,都自动为你解决了。详情可以看 ctex 宏包的[文档](http://tug.ctan.org/tex-archive/language/chinese/ctex/doc/ctex.pdf)。下面是一个小例子:

\documentclass{ctexart}
\begin{document}
你好,TeX Live 2009!
\end{document}

默认情况 (winfonts) 下,你需要宋体 (SimSun)、仿宋 (simfang)、黑体 (simhei)、楷体 (simkai)、隶书 (LiSu)、幼圆 (YouYuan) 这六套 Windows 字体,如果你的字体不全,可以编辑 `ctex-xecjk-winfonts.def` 文件 (用 `kpsewhich` 来找) 来修改设置,也可以选择 Adobe Reader 等软件所带的 Adobe Song Std, Adobe Heiti Std, Adobe Kaiti Std, Adobe Fangsong Std 四款字体,这时需要给 ctexart 加上 `[adobefonts]` 选项。又或者,你可以不用这些预置的字体,使用 `[nofonts]` 选项,然后参考 `ctex-xecjk-winfonts.def` 文件,自己定义对应各个 CJK 字体族的字体。

低层的方案则是用原来你自己的宏包,结合 xeCJK 宏包来配置字体,下面是一个小例子:

\documentclass{article}
\usepackage{xeCJK}
\setCJKmainfont{SimSun}
\begin{document}
你好,TeX Live 2009!
\end{document}

当然,你得有 SimSun 这个字体。

不管选用高层的还是低层的,都可以直接用 `xelatex` 命令直接编译你的文档。

#### 传统 CJK 方案

传统 CJK 方案主要是为了方便使用以前的文档存在的。也分为两种,高层方案也是使用 ctex 宏包,低层方案和原来的文档一样,直接用 CJK 宏包。

使用 ctex 宏包的例子和前面用 ctexart 的那个完全一样:

\documentclass{ctexart}
\begin{document}
你好,TeX Live 2009!
\end{document}

不过需要注意的是,你还得安装 `zhmetrics` 宏包。另外,如果文档保存的编码是 GBK,必须添加 `[GBK]` 选项,否则用 UTF-8 编码的也建议用 `[UTF8]` 选项。

可以看出,用高层方案最大的好处是文档代码可以最大限度地不修改就能换用不同的 TeX 引擎。

低层方案与原来的做法的区别是,需要载入 zhwinfonts,使用 zhwinfonts 定义的字体,而不是原来自己去生成字体的映射文件,这样要简便很多:

\documentclass{article}
\usepackage{CJK}
\input zhwinfonts
\begin{document}
\begin{CJK}{GBK}{zhsong}
你好,TeX Live 2009!
\end{CJK}
\end{document}

注意,这里用了 `zhsong` 这个字体族而不是 `song`,为了避免和 CJK 宏包原来定义的冲突,我们定义的所有字体族都带 `zh` 前缀。

对于上述这两种情况,你都可以使用 `latex` 编译,用 `dvipdfmx` 生成 pdf。

除了上述的 `zhmetrics`, `ctex`, `xeCJK` 宏包以外,我们还在 CTAN/TeX Live 中提交了 `zhspacing`, `CJKpunct`, `zh-luatex` 等宏包,`ctex-faq`, lshort 中文翻译等文档,以上工作都需要感谢参与维护 [ctex-kit](http://code.google.com/p/ctex-kit) 的全体开发者,为 [ctex-doc](http://code.google.com/p/ctex-doc) 贡献内容的全体作者,也欢迎你参加到我们的工作中来,帮助进一步改进 TeX 的中文支持。

闲聊文本渲染技术的近期发展

在今年 7 月的 [GUADEC](http://www.grancanariadesktopsummit.org/) 上 Behdad Esfahbod 做了一个题为 [State of Text Rendering](http://behdad.org/text/) 的讲座,系统地综述了当前文本渲染技术的现状,顺带强调主要由他开发的 [harfbuzz-ng](http://www.freedesktop.org/wiki/Software/HarfBuzz) 是未来发展的方向,4 个月过去了,最近文本渲染技术有了什么发展呢?这里谈谈我的一些印象和见解。

首先,harfbuzz-ng 到底想做成什么样子?我们知道底层的字体格式支持,开放的有 [FreeType](http://www.freetype.org) 一枝独秀,各平台私有的有 Win32 的 GDI font, Mac OS X 有 ATS 和 [CGFont](http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CGFont/Reference/reference.html),上层的文本布局排版引擎,现在各家自有一套到两套:Windows 的 [DirectWrite](http://en.wikipedia.org/wiki/DirectWrite) 和 Uniscribe;Mac OS X 有 Core Text 和 ATSUI,有 [NSLayoutManager](http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSLayoutManager_Class/Reference/Reference.html);GTK+ 有 [pango](http://www.pango.org/),都是比较成熟的接口了,那 harfbuzz-ng 是要取代他们吗?

不是,也完全说不通,毕竟 pango 就是 Behdad Esfahbod 自己维护的,没理由拆自己的台。但是开放的 pango 等平台一直缺失的部分是 OpenType 复杂排版特性的支持,这一点 FreeType 没来得及解决,也因为和排版引擎关系太紧密,所以没法完全靠 FreeType 这种“字体格式解析库”来解决。harfbuzz-ng 要做的,正是在原来的 FreeType OpenType 排版代码的基础上,构建一个类似 [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine) 的、有简洁的 C API 的、支持 OpenType 特性的,而且还要比 pango 底层一些的库。

那不是和 ICU 重合了吗?ICU 一来是 C++ 的 API 用着比较累,而来确实也比较笨重,移植的时候够受的。ICU 虽然在近期版本里也开始提供 C 的排版引擎 API,但也只是试验性的。

所以总的看起来,Linux 下的文本渲染层次还真是够多的:GTK+ → pango/[cairo](http://cairographics.org) → harfbuzz-ng → FreeType,同时 harfbuzz-ng 还可能用到 ICU, [Graphite](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&cat_id=RenderingGraphite),在 Mac OS X 上还要用到 Core Text 和 Core Graphics。

细分层带来的好处就是不同的需求可以选择合适的 API 来实现:比如你要在图形界面上显示一段文字,就用 GTK+ 的 label;要绘制小段的文本,就用 cairo 和 pango;要高效率的、轻量地绘制大量的文本,就用 harfbuzz-ng 来自己攒一个排版引擎 — 大部分浏览器都是这样,只不过在没有 harfbuzz-ng 的情况下,或者要直接用 FreeType,不得不多写很多代码,或者就用 pango 这种重量级的,性能又得不到保证。

在 8 月份,harfbuzz-ng 的 [API 提议](http://lists.freedesktop.org/archives/harfbuzz/2009-August/000359.html)已经出现,并在不断讨论中完善 (要我说,本来这个星球上有经验参与讨论的也最多不超过 20 个人,不如大家到一个屋子里开个会搞定得了)。

[XeTeX](http://www.tug.org/xetex/) 的作者 Jonathan Kew 虽然仍然在开发 [TeXworks](http://www.tug.org/texworks/),但工作的重心已经放到了 Mozilla Firefox 3.6 的 [WOFF](http://hacks.mozilla.org/2009/10/woff/) 格式和 OpenType 复杂排版支持上,最近的一个视频里 Jonathan 提供了一个[很棒的概览](http://hacks.mozilla.org/2009/10/font-control-for-designers/),有这样的一些特性之后,在浏览器里做一些**认真的**文本排版才可能成为现实 — 可惜浏览器仍然缺乏好的断行算法实现。这部分工作其实就是基于 harfbuzz-ng 的。而 WebKit-GTK 版本也开始了基于 harfbuzz-ng 的实现。

当然了,畅想了一番美好未来之后还是要回到现实,目前我想做的一个项目,是开发一套能跨 iPhone OS 和 Mac OS X 的、轻量级的排版引擎,专门给[文本阅读器](http://www.jjgod.org/projects/textus)用。这个工作的出发点是:

1. iPhone 上缺少 (按我的标准) 足够好的文本阅读器,而既然我已经开始写 Textus 了,不如把它移植到 iPhone 上;
2. iPhone 上没有 Core Text 这个层次的框架,要渲染文本要么用 `NSAttributedString`,要么用 `WebView`,他们的额外开销都太多,太重量级了;
3. 轻量的方法有神秘的 private API [`CGFontGetGlyphsForUnichars`](http://www.google.com/search?q=CGFontGetGlyphsForUnichars),如果不愿意用 private API 呢,就只好像 [cocos2d-iphone](http://code.google.com/p/cocos2d-iphone/) 那样自己去实现 [cmap 载入的代码](http://code.google.com/p/cocos2d-iphone/source/browse/trunk/external/FontLabel/FontLabelStringDrawing.m),非常痛苦;
4. 即使这样,也不支持复杂的 OpenType 排版特性,甚至简单一点的连字 (ligature) 都不支持,对于一个文本阅读器这是不能忍受的。

所以觉得写个这样的引擎会比较有用:

* 做到后端独立,比如可以选用 ICU (iPhone OS 上), Core Text (Mac OS X 上), harfbuzz-ng
* 能够支持 OpenType 复杂排版特性
* 至少支持好大部分西方字符和 CJK 字符
* API 尽可能的简单

最近刚刚开始做一些试验,比如用 Core Graphics 完成了一个简单的 [CGFontInstance](http://github.com/jjgod/texo/tree/master/icu/) 给 ICU 用,这在目前还没看到类似的工作。