jjgod / blog Random notes by Jjgod Jiang.

Posts Tagged ‘reader’

阅读器的进度显示与估计

对电子书阅读器来说,提示当前阅读进度是一项很自然的功能,习惯用电脑的人都常看到进度条 (progress bar) 和滚动条 (scroll bar),如右图是 Textus 中使用的右侧滚动条。 然而在实际实现中,进度计算是一件伤脑筋的事情,比如 Textus 的实现其实很简单:在打开文件时读入整个文件,然后整个交给 Core Text 去排版,将排版后的结果分解为行 (CTLineRef) 记录下来,并将所有行总的高度设置为整个文本视图的高度,这样,每当滚动视图 (NSScrollView) 移动到某个位置时,重绘函数 (-drawRect:) 被调用到,我们根据该位置来判断应该绘制从第几行到第几行的内容,再调用 Core Text 把这些行画出来。 这么做看似很简单直接,结果也很容易保证正确,带来的问题是,每次用户修改设置 (比如调整字体大小、窗口尺寸) 时,就得把整个文件重新排版一遍,即使此时我们只需要看到当前一页的内容。为什么这种方法这么低效,我还一直使用它呢?因为这个实现严格依赖滚动视图给出的位置来判断当前阅读进度,所以总的高度估计必须非常精确,不然随便滚动一下就可能出现错位,而一次算给出整个高度的方法最准确,不容易出错。 在 iTextus,也就是 iPad 版本的文本阅读器中,我打算换一种方法,主要的原因是: 大家在手持设备中都不喜欢用进度条,因为频繁滑动比较烦人 分页方式实现起来比较简单高效,而 iPad 的性能有限 其实从文件载入到显示出来,90% 的时间花费在排版上 (对于 Core Text 程序,就是 CTFramesetterCreateWithAttributedString 这一步),剩下 5% 用来读取文件,5% 用来绘制排版结果。所以在 iPad 上我们尽可能的减少排版时间,最简单的方法就是把这个时间均摊到每页上,这样每页的排版时间就几乎可以忽略不计了。另一方面,这样也能减少程序的内存占用,在内存紧张的时候可以简单地回收几个页面的排版数据,而不必清空所有的。 既然采用分页方式,进度显示就很灵活了,我们先看看常见的 iPhone 上电子书阅读器是怎么做的。 Stanza 在全屏阅读状态时,除了页面底部用不同颜色显示已读和未读进度比例之外,没有任何其他的提示,这样看起来非常简洁。 触碰页面中部之后 Stanza 会出现一个更详细的界面,包括上方的导航栏提供了书名和作者,中间提示了章节、页数和进度的百分比,下方工具栏还提供了直接通过拖拉跳转页面的功能。 [...]

A closer look at Classics.app

“Classics” is a great product, it shows us iPhone developers what an elegant ebook reader can be, so I bought it almost instantly after it’s released. I’ve been chatting with my friends about this app for a while, now I’d like to give a more closer examination to it from the perspective of a typographer [...]