主题:【原创】新时代新潮流WebOS 【1】 -- 邓侃
你这是两个人分析跟踪,俺一个人分析跟谁商量去?你那个单线程(Render Thread)的东西还比较“好”跟踪,这个多线程的东西,TNND。不过好处是俺又把DESIGN PATTERN和多线程设计的东西又重新REVIEW了一遍,顺便把CHROME团队的“先人”问候了N边。
不过底层的某些东西,让俺想起了芙蓉姐姐。WEBKIT的东西俺是不会深究的(起码一年内),现在俺一到胶水层(WEBKIT GLUE)就打住了。
上下有别。
看rails代码的时候,我也是边看代码边问候某些人,而且rails代码还算是非常好读的,webkit代码看的时候几近无语。
上花上花,最近手头有项目暂时没看代码了,等闲下来接着看,接着问候。老邓太守你们把骂娘的段子一起写上来一定好玩
拍砖都花样百出
有太守那样拍砖拍成系列的,上下文流程紧凑,各篇分工清晰,算是chain of responsibility吧
还有美人他爹那样,一般不大拍,一旦某个特征主题出现,立拍且准,算是observer吧
yueyu是巡视九边,无论主题还是跟贴,可拍即拍,主题贴有主题的拍法,跟贴有跟贴的拍法,砖砖不同,随贴而变,这个算state吧
我原先估摸着,再凑凑,能凑够23种
现在看着眼前这一帮预定板儿砖的,就不准备凑下去了,您看阿,这还没开拍呢,先把砖坑占好了,人家已经进化到动态语言阶段了,我还扯啥模式阿————坑先占,砖百变————这活脱脱是开放类阿~~~
而且老邓你还没办法制定防砖策略。。。
拜服。。。
就这么个简单又简单的网页,Webkit居然开了4根线程。
估计是main loop占用了一根。
Load HTML 文本文件占用了一根。
Load image又占用了一根。
还有一根不知道干什么用。
不太清楚Webkit依据什么准则开线程。等待太守详解。
赶紧来捧个场,省得下面又没了
不知道你是看的那个WEBKIT的代码?俺是用CHROME的代码看的结论。
这个是Chrome的BROWSER进程
这个是Chrome的renderer进程,WIBKIT代码在其中运行。Chromium_RendererMain是该进程的第一个线程 --- 主线程。负责与browser的通信,传输网络请求数据(信号),Chrome_ChildThread是真正的Render线程,跑WEBKIT代码。剩下的两个win32线程的目的有点像“看门狗”,由这个函数生成。
BOOL WINAPI RegisterWaitForSingleObject(
__out PHANDLE phNewWaitObject,
__in HANDLE hObject,
__in WAITORTIMERCALLBACK Callback,
__in PVOID Context,
__in ULONG dwMilliseconds,
__in ULONG dwFlags
);
.
我整天写sax tranformer经常觉得这个很麻烦。
我的办法是先把图上传到flickr,然后在贴图。
我这里跑的是QT环境下debug mode,不是chrome。第一根线程是QT的主线程,负责整个浏览器的mainloop。这个我们俩意见一致。
就文中的简单的例子来看,只有这一根线程在跑。但是在这个例子中没有JavaScript,没有UI Event响应。今天仔细看了一下,发现load HTML文本文件,以及load image的时候,也没有动用其它线程。
RegisterWaitForSingleObject()看来很有意思,尤其是那个callback。这几根看门狗线程,是不是用来响应UI Events的?
以后请多发言,讨论是深入研究的驱动力。
现在天天对着大型机干活,都快与世隔绝了
看着一众河友涌跃讨论这些自己曾投入很大热情的咚咚,“于我心有戚戚焉”
就不发言献丑了你们保持激情,我来加油
【21】WebKit,为了布局,忙并美丽着
如果没有1440年以后活字印刷术的大规模普及,或许就不会有文艺复兴运动,更不会有后来的启蒙运动。如果没有这两个运动的开展,或许就不会有世界范围的工业化。
在活字印刷术出现以前,每出版一本书,都必须先刻制一套模版,称为雕版,每套雕版上的每一个字,都是手工雕刻的。不仅制作雕版费时费力,而且有了错误不容易更改。活字印刷术的进步在于,可以预先批量生产各种样式和大小的字体,称为活字。需要出版某一本书籍时,先制作该书的页面模版,模版做好以后,只需要把这些活字摆放在模版上即可。如果出现错误,只需要调换某些活字,既省时又省力。如果某本书的模版不需要长期保存,还可以把模版中摆放的活字拆解下来,在印刷其它图书时用,节约成本。
活字印刷术没有解决的问题,1. 图像的印刷。起初不能印刷笔触丰富,层次复杂的图像,一直到1796年,石板印刷术(lithography)出现以后,才能印刷表现手段丰富的图像。 2. 灵活的布局排版。纸张大小不同,布局排版也不同,布局变了,需要重新摆放活字,而且有时候还需要改变字体和大小。
灵活的布局排版对于纸质书籍来说,或许并不太重要,但是对于电脑浏览器来说,却必须实现完全的自动化。否则,每当用户改变浏览器窗口的大小的时候,页面内容就不能正确显示。对于手机浏览器来说,布局排版的自动化尤其重要,因为不同手机的屏幕不一致,而且屏幕分辨率也不同。
但是即便是浏览器,也没有摆脱传统的排版方式。所谓传统的排版方式,基本是横平竖直的,单一的鸟瞰视角。
Figure 1. Incunabulum, the end of 15'th century
Courtesy http://www.citrinitas.com/history_of_viscom/images/printing/venice-1505.jpg
Figure 2. City of Words, by Vito Acconi, 1999
Courtesy http://upload.wikimedia.org/wikipedia/en/6/63/%27City_of_Words%27%2C_lithograph_by_Vito_Acconci%2C_1999.jpg
Figure 1 中显示的是1490年代的书籍,不难看出,现代书报中广泛使用的双列,边注,页码,首字母大写等等,都是继承了500多年以前的做法。而CSS规范,囊括了所有这些页面设计的要素。
在当今信息爆炸的形势下,如何安排页面的布局排版,在有限的页面面积内,承载更多内容,突出读者关注的内容,增强页面设计的视觉美感,成为不可回避的问题。例如,手机购物的UI设计,既要包含商品简介,又要包含用户意见反馈,还要包含实物照片,以及各个不同商场的标价等等。完美的页面设计,不仅要求简练而清晰,而且也不能遗漏相关内容,实在是一件困难的事情。可以说,手机购物之所以不普及,与手机购物的UI设计笨拙而丑陋是相关的。
要巧妙地设计手机应用的UI设计,终极而言,需要突破传统的单一鸟瞰视角的方式,Figure 2 就是这方面的尝试。Webkit能不能做到这一点?原理上是可以做到的,但是必须修改源代码。但是在改造以前,我们还是先踏踏实实研究一下,Webkit 的布局排版的内部机制是什么。只有充分了解对方之长,才有可能改进对方之短。
读解Webkit排版布局与绘制的具体实现以前,首先需要明确的是,Webkit把排版布局(layout),与绘制(paint),分开处理。
Layout负责确定Render Tree中,每个叶子和中间节点的位置。每个节点在屏幕上的显示,都呈长方形格局。所谓位置,指的是这个长方形左上角起始坐标(X,Y),以及长方形的宽度和高度。每个中间节点的长方形,里面嵌套着若干小长方形,对应这个中间节点的后代节点等等。
在Layout过程结束以后,Webkit启动 Paint过程,负责把Render Tree中各个叶子节点,在相应的位置绘制出来。Webkit 把具体绘制的工作,交给第三方图形工具库(Graphics Library)去完成。常用的第三方图形工具库包括QT,GTK+,Wx,Skia,Cairo等等。
打个比方,图形工具库相当于活字,以及绘制图像的石板(lithography),它们负责paint。而从严格意义上来说,Webkit的主要工作是layout,也就是排版布局,相当于版面模版。
关于图形库,台湾的开源高手,黄敬群(Jim Huang / jserv),写过一篇介绍Google Skia 图形库的文章(http://blog.linux.org.tw/~jserv/archives/002095.html)。文中谈到,
Google 为了搭建Android平台,于2005年8月并购了Android公司。同年11月份,Google还收购了Skia公司。2007年11 月,Google发布Android,并公开部分源代码。当人们热衷于探究Android Dalvik VM的奥秘的时候,忽略了Skia的意义。
2008年9月,Google发布了以改良的Webkit为核心的Chrome PC浏览器。当人们热衷于探究V8 JavaScript引擎等等功能模块时,再次忽略了Skia的意义。
Skia是一个2D图形工具库,该产品的特色在于,能够在手机等等移动设备中,以较低的内存和CPU消耗,呈现高品质的2D图形。
Skia 的创办人,Michael Reed,是图形技术方面的顶尖人物。Michael早年任职于Apple,参与QuickDraw GX项目,处理字型和图像显示。后来他跳槽到OpenWave,开发手机浏览器。在OpenWave工作期间,与Benoit Schillings合作,在50-300KB的内存空间内,提供图层之间alpha blended方式的预览,以及全功能向量矩阵转换等等,真可谓螺丝壳里做道场。后来Benoit Schillings离开OpenWave,去Trolltech任职CTO。Trolltech的主打产品是大名鼎鼎的QT。再后来Trolltech 被Nokia并购,Benoit随之加入Nokia。Benoit Schillings离开OpenWave不久,Michael Reed也离开了OpenWave,去创建Skia公司。
Figure 3. Layout implementation in Webkit
Courtesy http://www.flickr.com/photos/87209438%40N00/3609632247/sizes/l/
Figure 4. Paint implementation in Webkit
Courtesy http://www.flickr.com/photos/87209438%40N00/3609632249/sizes/l/
Figure 3 和 Figure 4, 分别显示了Webkit执行排版布局(layout),以及绘制(paint)的两个过程。仔细查看这两张sequence diagrams,会发现以下特点,
1. Layout 和 Paint 这两个过程完全分开。开始执行Paint过程以前,必然预先执行过Layout,否则图形库就不知道在哪里写字以及显示图像。但是这并不意味着,Layout执行结束后,随即就立刻执行Paint。实际上,Layout执行结束后,触发一个事件,这个事件启动Paint过程。但是Paint过程也可以被其它事件触发,譬如屏幕内容的切换,以及把隐藏的浏览器窗口复原等等。
2. Layout 涵盖了所有CSS规定的布局要素。包括页面边缘与内容之间的空白,文字对插入图像的避让(floating),单列与多列,上下层覆盖(z-index)等等。
3. 图像,视频播放器插件,Applet等等,在 Layout 被称作 Replaced Render Object。这些 Replaced 元素的宽度和高度可以由CSS规定。如果CSS没有规定,就解析这些元素的数据流,譬如一个JPG照片的metadata里,规定了这幅照片原件的宽度和高度。如果元素自己也没有规定宽度高度,就使用Webkit提供的缺省值。
4. 文字的宽度根据页面的排版来确定。譬如一页中包含多列文字,则每列文字宽度相等。每列文字的宽度,乘以列数,加上列与列之间的夹缝,加上页面边缘空白等等,应当等于页面总的宽度。假设页面总的宽度已知,边缘空白,和列与列之间的夹缝的宽度也已知,就可以反推文字的宽度。
5. Render Tree中每个节点在屏幕上的显示,都呈长方形格局。前面第3点和第4点,描述了宽度的确定。而高度的确定,取决于这个中间节点的所有后代节点的高度的总和。对于 Replaced 元素来说,它的高度相对比较容易确定,而文字段落的高度,需要根据字数,字型,以及字体大小计算得出。
6. 在 Layout 过程中,反复出现以 Repaint 为开头的子过程,例如 repaintAfterLayoutIfNeeded()。这些子过程的意义在于,当确定了某个节点的高度和宽度以后,需要对其前辈节点,和左右兄弟节点的位置,做适当调整。严格意义上来讲,这不是repaint,而是relayout。
7. 相对于 Layout 过程,Paint 过程的逻辑要简单得多。Paint的过程,大致按照深度优先的顺序,遍历整棵RenderTree。也就是说,从最左边的叶子节点开始,从左向右逐个绘制 RenderTree所有可以显示的叶子节点。所谓“可以显示的叶子节点”,是因为CSS中可以规定,不显示某些叶子。
反复研究以上Layout和Paint的过程,我们有以下看法。
1. Layout 是一个计算量很繁重的过程。之所以繁重,主要体现在估算完每个RenderTree节点的宽度尤其是高度以后,需要相应调整这个节点的前辈节点以及左邻右舍兄弟节点的位置。对于文字段落而言,它的高度有赖于字数,字体和大小,所以估算不容易准确。
有没有可能把Layout 过程,与第一遍 Paint 过程合二为一?只要遍历一次RenderTree的所有叶子节点,绘制图像并码字。Paint过程结束后,各个叶子节点对应的长方形的起始位置的(X,Y)坐标,以及宽度和高度都自然迎刃而解。然后再由叶子节点开始,逐步确定RenderTree中,各个中间节点的起始位置和宽度高度。这样做的好处是,可以大大降低 Layout 过程的成本。
2. Layout 过程假设每个RenderTree 的节点都对应一个长方形屏幕区域。受限于这个规定,类似于Figure 2的效果,就显示不出来。有没有可能取消这个限制?SVG不仅提供了强大的绘图能力,而且也提供了强大的排版布局能力。能不能把CSS当着SVG格式的一个子集来看待?