<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jjgod / blog &#187; reader</title>
	<atom:link href="http://blog.jjgod.org/tag/reader/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jjgod.org</link>
	<description>Random notes &#38; thoughts by Jiang Jiang.</description>
	<lastBuildDate>Mon, 16 Jan 2012 11:08:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>阅读器的进度显示与估计</title>
		<link>http://blog.jjgod.org/2010/04/22/progress-in-a-reader/</link>
		<comments>http://blog.jjgod.org/2010/04/22/progress-in-a-reader/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 09:21:03 +0000</pubDate>
		<dc:creator>jjgod</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Typography]]></category>
		<category><![CDATA[coretext]]></category>
		<category><![CDATA[eucalyptus]]></category>
		<category><![CDATA[goodreader]]></category>
		<category><![CDATA[reader]]></category>
		<category><![CDATA[stanza]]></category>
		<category><![CDATA[textus]]></category>

		<guid isPermaLink="false">http://blog.jjgod.org/?p=616</guid>
		<description><![CDATA[对电子书阅读器来说，提示当前阅读进度是一项很自然的功能，习惯用电脑的人都常看到进度条 (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 会出现一个更详细的界面，包括上方的导航栏提供了书名和作者，中间提示了章节、页数和进度的百分比，下方工具栏还提供了直接通过拖拉跳转页面的功能。 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Textus.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Textus.png" alt="" title="Textus" width="68" height="368" class="alignright size-full wp-image-618 noline" /></a>
对电子书阅读器来说，提示当前阅读进度是一项很自然的功能，习惯用电脑的人都常看到进度条 (progress bar) 和滚动条 (scroll bar)，如右图是 <a href="http://www.jjgod.org/projects/textus">Textus</a> 中使用的右侧滚动条。</p>

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

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

<p><span id="more-616"></span></p>

<p>在 iTextus，也就是 iPad 版本的文本阅读器中，我打算换一种方法，主要的原因是：</p>

<ul>
<li>大家在手持设备中都不喜欢用进度条，因为频繁滑动比较烦人</li>
<li>分页方式实现起来比较简单高效，而 iPad 的性能有限</li>
</ul>

<p>其实从文件载入到显示出来，90% 的时间花费在排版上 (对于 Core Text 程序，就是 <code>CTFramesetterCreateWithAttributedString</code> 这一步)，剩下 5% 用来读取文件，5% 用来绘制排版结果。所以在 iPad 上我们尽可能的减少排版时间，最简单的方法就是把这个时间均摊到每页上，这样每页的排版时间就几乎可以忽略不计了。另一方面，这样也能减少程序的内存占用，在内存紧张的时候可以简单地回收几个页面的排版数据，而不必清空所有的。</p>

<p>既然采用分页方式，进度显示就很灵活了，我们先看看常见的 iPhone 上电子书阅读器是怎么做的。</p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Stanza-1.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Stanza-1.png" alt="" title="Stanza-1" width="320" height="100" class="alignleft size-full wp-image-624" /></a>
<a href="http://www.lexcycle.com/">Stanza</a> 在全屏阅读状态时，除了页面底部用不同颜色显示已读和未读进度比例之外，没有任何其他的提示，这样看起来非常简洁。</p>

<p>触碰页面中部之后 Stanza 会出现一个更详细的界面，包括上方的导航栏提供了书名和作者，中间提示了章节、页数和进度的百分比，下方工具栏还提供了直接通过拖拉跳转页面的功能。</p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Stanza-2.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Stanza-2.png" alt="" title="Stanza-2" width="50%" class="centered wp-image-625" /></a></p>

<p><a href="http://www.goodiware.com/goodreader.html">GoodReader</a> 在全屏阅读时干脆什么都不显示，触碰页面中部之后的界面和 Stanza 差不多，不同之处是把页面和跳转进度条放到了左边。</p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/GoodReader-1.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/GoodReader-1.png" alt="" title="GoodReader-1" width="80%" class="centered size-full wp-image-631" /></a></p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Eucalyptus-1.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Eucalyptus-1.png" alt="" title="Eucalyptus-1" width="320" height="187" class="alignleft size-full wp-image-633" /></a>
<a href="http://eucalyptusapp.com/">Eucalyptus</a> 采用的是模仿真实书籍的方式，全屏时在页面上方显示书名和页码。</p>

<p>在触碰页面中部之后，Eucalyptus 显示的界面和 Stanza 差不多，更简单一点，中间没有放置任何 HUD 控件，页码放在了下方，而且干脆也不提供任何设置功能了。</p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Eucalyptus-2.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Eucalyptus-2.png" alt="" title="Eucalyptus-2" width="50%" class="centered wp-image-635" /></a></p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/Classics.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/Classics.png" alt="" title="Classics" width="50%" class="alignright wp-image-640" /></a>
<a href="http://www.classicsapp.com/">Classics</a> 的方式更有趣一些：它没有单独的信息界面，导航栏是一直保持在页面上部的，书名在导航栏上，然而它改写了导航栏，在上面通过颜色区分显示阅读过和尚未阅读的进度比。下方则用浅色显示章节名称和页码。</p>

<p>其他几个阅读器主要是考虑 iPhone 界面空间非常宝贵，导航栏和状态栏没必要随时保持在页面上，把它们在用户要求时单独显示出来反而不容易干扰阅读，而 Classics 这种做法也是可以理解的，因为它复用了导航栏，算是节省了一些空间，这样实现也简单一点。</p>

<p>此外，Stanza 和 GoodReader 都支持横屏显示，而 Eucalyptus 和 Classics 都不支持。</p>

<p>目前我在 iTextus 中实现的是类似 Stanza 的进度提示方式，如下图所示，因为这是最容易实现的，至于最后是否应该选择这样的方式，我还没有决定，也欢迎你的意见。</p>

<p><a href="http://blog.jjgod.org/wp-content/uploads/2010/04/iTextus-1.png"><img src="http://blog.jjgod.org/wp-content/uploads/2010/04/iTextus-1.png" alt="" title="iTextus-1" width="480" class="center wp-image-648" /></a></p>

<p>与进度显示紧密相关的是进度的估计，因为我们既然不能一次排版完所有内容，就必须有个合适的方法估计当前阅读内容的总页数，目前我采用的一个简单的方法如下：</p>

<ol>
<li>因为我们一次读取整个文件的内容，所以一开始我们就知道当前文件的总长度 (字符数量)</li>
<li>但是每页可能有不同数量的字符 (比如有的页面段落、换行较多，有的则较密集)，可是我们假设平均数量是一个稳定值</li>
<li>总的估计页数 = 文件总的字符数量 / 当前页面平均字符数得到</li>
<li>一开始只排版了一个页面，那当前的页面平均字符数就是第一页的字符数，此后每排版一个新的页面，我们可以让这个平均值更精确一点</li>
</ol>

<p>经过实际使用的尝试，对于较长的文件 (比如文本长度 100KB 以上的)，这个页数估计是非常精确的，就算偶尔出现震荡也不会超过一两页，不会影响用户对进度的体验。</p>

<p>前不久 <a href="http://www.instapaper.com/">Instapaper</a> 的开发者 <a href="http://www.marco.org/">Marco</a> 提出了一个新的想法：根据时间跟踪和估计进度，大致构思如下：</p>

<ol>
<li>从用户打开一个新的文件开始，记录用户阅读该文件的总时间</li>
<li>用户的平均阅读速度 = 该文件总阅读时间 / 当前已阅读的页数 (或者字数？)</li>
<li>根据总的页数或者字数和用户的平均阅读速度推算要读完这本书要花费的总时间</li>
<li>可以在界面中显示从现在开始，如果不间断，将在什么时刻读完这本书</li>
</ol>

<p>这毫无疑问是一个比较有意思的想法，其实游戏和播放器都经常采用这样的方式 (时间记录和完成时间估计)，但用在书籍、文章阅读时会起到积极的作用吗？会不会有些副作用？不惯怎么说，应该是值得尝试的。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jjgod.org/2010/04/22/progress-in-a-reader/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>A closer look at Classics.app</title>
		<link>http://blog.jjgod.org/2008/11/30/a-closer-look-at-classicsapp/</link>
		<comments>http://blog.jjgod.org/2008/11/30/a-closer-look-at-classicsapp/#comments</comments>
		<pubDate>Sun, 30 Nov 2008 04:36:01 +0000</pubDate>
		<dc:creator>jjgod</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Miscs]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Typography]]></category>
		<category><![CDATA[classics]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[reader]]></category>

		<guid isPermaLink="false">http://blog.jjgod.org/?p=271</guid>
		<description><![CDATA[“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&#8217;s released. I&#8217;ve been chatting with my friends about this app for a while, now I&#8217;d like to give a more closer examination to it from the perspective of a typographer [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://omploader.org/vejRk/classics-1.png" alt="A Screenshot of Classics" class="left"  /></p>

<p>“<a href="http://www.classicsapp.com/">Classics</a>” is a great product, it shows us iPhone developers what an <em>elegant</em> ebook reader can be, so I bought it almost instantly after it&#8217;s released. I&#8217;ve been chatting with my friends about this app for a while, now I&#8217;d like to give a more closer examination to it from the perspective of a typographer and a programmer. Especially its weaknesses.</p>

<p>Illustrated by my favorite graphic designer, <a href="http://dlanham.com">David Lanham</a>, Classics tries its best to provide a traditional book reading experience (that&#8217;s why it&#8217;s called &#8220;Classics&#8221;). It contains the following books, even I&#8217;ve read most of them in Chinese long time ago, thanks to Classics, it&#8217;s still a fascinating experience to read them again in English:</p>

<ul>
<li><em><a href="http://en.wikipedia.org/wiki/Twenty_Thousand_Leagues_Under_the_Sea">20,000 Leagues Under the Sea</a></em> by <a href="http://en.wikipedia.org/wiki/Jules_Verne">Jules Verne</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/A_Christmas_Carol">A Christmas Carol</a></em> by <a href="http://en.wikipedia.org/wiki/Charles_Dickens">Charles Dickens</a> [Added in version 1.1]</li>
<li><em><a href="http://en.wikipedia.org/wiki/Alice_in_Wonderland">Alice in Wonderland</a></em> by <a href="http://en.wikipedia.org/wiki/Lewis_Carroll">Lewis Carroll</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Flatland">Flatland</a></em> by <a href="http://en.wikipedia.org/wiki/Edwin_Abbott_Abbott">Edwin Abbott Abbott</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Gulliver%27s_Travels">Gulliver&#8217;s Travels</a></em> by <a href="http://en.wikipedia.org/wiki/Jonathan_Swift">Jonathan Swift</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Hound_of_the_Baskervilles">The Hound of the Baskervilles</a></em> by Sir <a href="http://en.wikipedia.org/wiki/Arthur_Conan_Doyle">Arthur Conan Doyle</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Adventures_of_Huckleberry_Finn">Adventures of Huckleberry Finn</a></em> by <a href="http://en.wikipedia.org/wiki/Mark_Twain">Mark Twain</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Paradise_Lost">Paradise Lost</a></em> by <a href="http://en.wikipedia.org/wiki/John_Milton">John Milton</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/Robinson_Crusoe">Robinson Crusoe</a></em> by <a href="http://en.wikipedia.org/wiki/Daniel_Defoe">Daniel Defoe</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/The_Call_Of_The_Wild">The Call of the Wild</a></em> by <a href="http://en.wikipedia.org/wiki/Jack_London">Jack London</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/The_Jungle_Book">The Jungle Book</a></em> by <a href="http://en.wikipedia.org/wiki/Rudyard_Kipling">Rudyard Kipling</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/The_Metamorphosis">The Metamorphosis</a></em> by <a href="http://en.wikipedia.org/wiki/Franz_Kafka">Franz Kafka</a></li>
<li><em><a href="http://en.wikipedia.org/wiki/The_Time_Machine">The Time Machine</a></em> by <a href="http://en.wikipedia.org/wiki/H._G._Wells">H. G. Wells</a></li>
</ul>

<p>However, there are still some details to be improved.
<span id="more-271"></span></p>

<p><img src="http://omploader.org/vejRl/classics-2.png" alt="Classics's mistakes on word spacing and hyphenation" class="right"  /></p>

<p>First of all, Classics shows the entire interface in a portrait way, it&#8217;s more like traditional books, but has an unavoidable drawback: the iPhone/iPod Touch screen is not wide enough, if you make the characters large enough (otherwise people won&#8217;t be able to read them clearly), breaking paragraphs into lines will be extraordinarily hard, you either have to introduce a lot of hyphens, or make the word spacing too loose or too tight. From the following screenshot, we can see Classics made both mistakes.</p>

<p>The spots I marked made the reading experience much worse, if you&#8217;re a picky reader like me. And it happens on <em>almost every</em> pages! So why, why couldn&#8217;t Classics support landscape mode to improve the situation a little bit?</p>

<p>To understand this, we must first find out how Classics is implemented. Let&#8217;s take a look (yeah I know I shouldn&#8217;t do such reverse-engineering, but I just can&#8217;t help). First, copy it from where it&#8217;s saved, expand it as a zip archive:</p>

<pre><code>$ cp ~/Music/iTunes/Mobile\ Applications/Classics\ 1.1.ipa classics.zip
$ unzip classics.zip
    Archive:  classics.zip
   creating: Payload/
   creating: Payload/Classics.app/
   creating: Payload/Classics.app/20,000 Leagues.classic/
  inflating: Payload/Classics.app/20,000 Leagues.classic/0.pdf  
  inflating: Payload/Classics.app/20,000 Leagues.classic/1.pdf  
 ...
  inflating: iTunesMetadata.plist    
  inflating: Payload/Classics.app/SC_Info/Classics.sinf  
  inflating: iTunesArtwork           
finishing deferred symbolic links:
  Payload/Classics.app/CodeResources -&gt; _CodeSignature/CodeResources
</code></pre>

<p>OK, now it&#8217;s clearer, let&#8217;s open up Finder so that you can see it in a more structured way:</p>

<p><img src="http://omploader.org/vejRq/classics-3.png" alt="Internal structure of Classics" /></p>

<p>See? It turns out every book Classics loads and displays:</p>

<ol>
<li>Is a .classic ended directory with PDFs for each chapter,</li>
<li>Contains a <code>Info.plist</code> describes it,</li>
<li>Has a cover image called <code>Art.png</code>.</li>
</ol>

<p>Let&#8217;s first look at one of these plists,</p>

<pre><code>$ cd Payload/Classics.app/A\ Christmas\ Carol.classic
$ plutil -convert xml1 Info.plist -o -
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;author&lt;/key&gt;
    &lt;string&gt;Charles Dickens&lt;/string&gt;
    &lt;key&gt;language&lt;/key&gt;
    &lt;string&gt;English&lt;/string&gt;
    &lt;key&gt;sections&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;Preface&lt;/string&gt;
        &lt;string&gt;Marley’s Ghost&lt;/string&gt;
        &lt;string&gt;The First of the Three Spirits&lt;/string&gt;
        &lt;string&gt;The Second of the Three Spirits&lt;/string&gt;
        &lt;string&gt;The Last of the Spirits&lt;/string&gt;
        &lt;string&gt;The End of It&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;title&lt;/key&gt;
    &lt;string&gt;A Christmas Carol&lt;/string&gt;
    &lt;key&gt;year&lt;/key&gt;
    &lt;string&gt;1843&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre>

<p>So the file contains sufficient metadata for Classics to load this book, but it seems quite &#8220;preliminary&#8221;, thus, not flexible enough IMHO. For instance, PDF files must be named from 0 to n, each corresponds to a chapter (0 &rarr; Preface, 1 &rarr; Marley’s Ghost, etc.)</p>

<p><img src="http://omploader.org/vejR4/classics-4.png" alt="A Chapter from Alice in Wonderland" class="left" /></p>

<p>And then, how are these PDFs look? Here is a screenshot taken from Quick Look. <a href="http://linuxcommand.org/man_pages/pdffonts1.html">pdffonts</a> and <a href="http://linuxcommand.org/man_pages/pdfinfo1.html">pdfinfo</a> from <a href="http://www.foolabs.com/xpdf">xpdf</a> can give us more information:</p>

<pre><code>$ pdfinfo 0.pdf 
Title:          untitled4
Author:         Phillip Ryu
Creator:        Pages
Producer:       Mac OS X 10.5.4 Quartz PDFContext
CreationDate:   Fri Nov 14 00:12:37 2008
ModDate:        Fri Nov 14 00:12:37 2008
Tagged:         no
Pages:          2
Encrypted:      no
Page size:      216 x 316.8 pts
File size:      27175 bytes
Optimized:      no
PDF version:    1.3
</code></pre>

<p>So it&#8217;s typesetted manually by <a href="http://phillryu.com/">Phillip Ryu</a> with <a href="http://www.apple.com/iwork/pages/">Pages</a>, doesn&#8217;t sound very high-tech, huh?</p>

<pre><code>$ pdffonts 0.pdf 
name                                 type              emb sub uni object ID
------------------------------------ ----------------- --- --- --- ---------
VLFBFB+Georgia                       TrueType          yes yes no      10  0
LMPSPR+Georgia-Bold                  TrueType          yes yes no       9  0
BXMTAW+Georgia-Italic                TrueType          yes yes no      19  0
</code></pre>

<p>Yeah, the only font family used is <a href="http://en.wikipedia.org/wiki/Georgia_(typeface)">Georgia</a>. To admit, I was actually hoping some fonts more suitable for book typesetting, say, <a href="http://en.wikipedia.org/wiki/Garamond">Garamond</a> or <a href="http://en.wikipedia.org/wiki/Sabon">Sabon</a>.</p>

<p>Enough said, now we have a better understanding of the internal architecture of Classics. As we can see, using PDF for all the books is the chief decision that affects the rest of the app. There are pros and cons for this decision.</p>

<p>Pros:</p>

<ol>
<li>No need to calculate the layout when the user is reading, thus loading a new page will be generally faster than a book reader that loading text and doing layout dynamically.</li>
<li>With PDF, one can embeded arbitrary fonts as wish, bypassing iPhone&#8217;s limitation. (Classics does not make use of this advantage, sadly.)</li>
</ol>

<p>Cons:</p>

<ol>
<li>The layout is fixed, no way to adapt it to a screen in landscape mode.</li>
<li>Loading PDF through iPhone still has noticeable sluggish, thus, you can&#8217;t tap a chapter and have it shown instantly. The worse thing is, there is no way for the developer to optimize it, as long as they still use Apple&#8217;s frameworks for PDF rendering.</li>
</ol>

<p>Except for this, is there anything else can be improved? Yes,</p>

<ul>
<li><p>After compressed, Classics is a 22M beast. Downloading it in bad bandwidth condition can be a problem, not to mention every once it&#8217;s updated, you have to download 22M (or even more) again, while most of them you downloaded are just duplicated resource files you already had!</p>

<p>Even though we can see it greatly simplified application deployment, this part can certainly be improved. For instance, instead of bundle these books with the app, setup a site for it to retrieve books dynamically, books can be downloaded the first time user tries to read, and cached in his Documents directory.</p></li>
<li><p>Pages is definitely not a serious typesetting tool. If I were Phillip<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, I&#8217;ll try to build an automatic conversion infrastructure with <a href="http://www.tug.org/xetex">XeTeX</a>, it will be much easier to maintain, and gives noticeably better text layout results, especially on line breaking, I suspect.</p></li>
</ul>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>However, if I&#8217;m really going to implement such a book reader, PDF won&#8217;t be the best option for me though.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.jjgod.org/2008/11/30/a-closer-look-at-classicsapp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

