个人工具

Linux发行版浅谈

来自Ubuntu中文

跳转至: 导航, 搜索

发行版的开发模式

发行版的发展

GNU/LINUX最原始发布的是一个个源码包,早期的LINUX用户们获得源码包后需要自行编译安装配置,这给想要体验尝试LINUX的用户是带来的极大的不便,于是出现了 LINUX Distribution Package,也就是我们目前经常谈到的发行版,早期的LINUX发行版开始引入了包管理的概念。

包管理系统发展

最早的发行版是Slackware,Slackware Linux可以很容易的安装、升级、移除包。Slackware发行版中的包都经过gzip压缩和tarball打包,但文件扩展名是.tgz,而不是.tar.gz。他们的结构是这样的:当在根目录下解压缩和释放,其中的文件会放置于它们的安装位置,但是它不会试着去追踪或者管理涉及哪些依赖关系(也就是保证系统拥有所有的安装包内的程序需要的系统库)。如果所需要的先决条件不能满足,在程序执行之前不会有提醒和指示。也就是说Slackware的包管理方式的本质还是基于压缩解压缩的管理方式,相对的 Red Hat Linux 的RPM是CPIO档案,Debian Linux的.deb文件是则是ar档案。这些新的归档文件还包括一些依赖关系的信息,包管理器工具可以使用这些信息来寻找和安装先决条件。他们在先决条件满足前是不会安装新包的(虽然可以强制进行)。

在那个网络并不发达,软件资源并不丰富的的年代,一张DVD可以是LINUX的全部,当网络的浪潮涌来以后,debian率先推出了APT(Advanced Packaging Tools,简称:APT)工具,APT是Debian及其派生发行版的软件包管理器。APT可以自动下载,配置,安装二进制或者源代码格式的软件包,因此简化了Unix系统上管理软件的过程。APT最早被设计成dpkg的前端,用来处理deb格式的软件包。现在经过APT-RPM组织修改,APT已经可以安装在支持RPM的系统管理RPM包。后来Redhat则推出拥有同等功能的YUM工具,此后,更加方便的图形化包管理工具,synaptic(以apt为后端),yumex(以yum为后端),还有试图成为一个跨发行版本及跨架构 API 的 Linux 通用包管理器PackageKit,它将支持以 yum、conary、apt、box、pacman/alpm 等做为后端。

前面我谈到了包管理器的发展,包管理器是Linux发行版本的重要组成部分,甚至可以说因为包管理器的出现,才让Linux发行版本百花齐放,据 http://distrowatch.com 网站收录的统计结果,全世界约有314个Linux发行版,在这众多的发行版中 debian,slackware,redhat,gentoo,arch,等,下面我们谈谈如何发布和管理这些组成发行版的包,

最原始的发布的形式的压缩的tar包,安装的时候,需要自己解压,编译,安装,最早的Linux发行版slackware包管理就是基于这种最本质,最简单的理念,因为是最简单,但是也需要它的用户拥有丰富的经验与知识来配置,管理,维护这个系统。以后以redhat和debian为代表性的Linux发行版引入了带有控制格式的的src.rpm包和dsc源码包,用来编译和rpmbuild dpkg-buildpanckage dpkg-source


mock pbuilder koji ddbuild

工具链

GNU工具链 (GNU Toolchain) 是一组用于开发应用程序和操作系统的编程工具的集合,这些工具构成了一个完整的运行与开发环境。GNU工具链包括GCC、GNU Binutils、GNU m4、GNU Autoconf和GNU make等部分,而gcc、binutils和glibc则是除内核之外整个LINUX系统的基石,当发行版版本升级的时候,会先确定下一版本的kernel,gcc、binutils和glibc的版本,然后以此为基础,构建一个全新的环境,构建这个开发环境的过程。

  GNU工具链 (GNU Toolchain) 是一组用于开发应用程序和操作系统的编程工具的集合,这些工具构成了一个完整的系统。GNU工具链包括GCC、GNU Binutils、GNU m4、GNU Autoconf和GNU make等部分。这里主要介绍GCC、Binutils和Glibc。

LLVM 是 Low Level Virtual Machine 的简称,这个库提供了与编译器相关的支持,能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。简而言之,可以作为多种语言编译器的后台来使用。如果这样还比较抽象的话,介绍下 Clang 就知道了:Clang 是一个 C++ 编写、基于 LLVM、发布于 LLVM BSD 许可证下的 C/C++/Objective C/Objective C++ 编译器,其目标(之一)就是超越 GCC。

LLVM 是 Illinois 大学发起的一个开源项目,它到底是什么呢?从字面上看,它是一个虚机系统,然而这又和之前为大家所熟知的 JVM 以及 .net Runtime 这样的虚机不同,它提供了一套中立的中间代码和编译基础设施,并围绕这些设施提供了一套全新的编译策略(使得优化能够在编译、连接、运行环境执行过程中, 以及安装之后以有效的方式进行)和其他一些非常有意思的功能。

为什么这个项目很重要呢?对于普通的开发人员来说,LLVM计划提供了越来越多的可以使用、编译器以外的其他工具。例如代码静态检查工具 LLVM/Clang Static Analyzer,是一个 Clang 的子项目,能够使用同样的 Makefile 生成 HTML 格式的分析报告;而对关注编译技术的开发人员来说,LLVM提供了很多优点:

现代化的设计:LLVM的设计是高度模块化的,使得其代码更为清晰和便于排查问题所在。 语 言无关的中间代码:这使得透过LLVM能够将不同的语言相互连结起来;另一方面,这也使得LLVM能够紧密地与IDE交互和集成。另一方面,发布中间代码 而非目标代码能够在目标系统上更好地发挥其潜能而又不伤害可调试性(i.e. 在目标系统上针对本机的硬件环境产生目标代码,但又能够直接通过中间代码来进行行级调试) 作为工具和函数库:使用LLVM提供的工具可以比较容易地实现新的编程语言的优化编译器或VM,或为现有的编程语言引入一些更好的优化/调试特性。 一些值得关注的基于LLVM的项目:

CLang C/ObjC/C++ 编译器。目前C++部分还需要很多工作,但C的部分已经比较成熟了。这个项目还有一个子项目是 LLVM/Clang Static Analyzer。

llvmruby 基于LLVM的一个Ruby实现。

Unladen Swallow 是 Google 发起的,使用 LLVM 替换 Python VM 的项目,其目标是提供更好的性能。

LLVM项目还提供了一些针对有意使用LLVM来实现新的编译器/优化工具的开发人员的 教程。


除了GNU提供的工具链外,

GNU Compiler Collection

  GCC全称GNU Compiler Collection,其主要的工具包括cpp、g++、gcc、gcov、gprof等。其中cpp是C预处理器,主要用于在编译C、C++或Objective-C源代码之前对它们进行预处理,由编译器自动调用;g++和gcc可以大致认为分别是C++和C编译器 (当然,事实上它们都只是driver程序,分别再调用cc1plus、cc1和汇编器、链接器而已);gcov是一个检测代码覆盖率的工具,gprof是一个profile工具,这两个工具主要是跟GCC配合来分析并提高程序的性能,此时应用程序进行编译的时候需要使用类似以下方法:CFLAGS="-fprofile-arcs -ftest-coverage" ./configure --config-options(./configure –help)。

GNU Binutils

  GNU Binutils (Binary Utilities) 是一组二进制工具集。其中主要的两个工具是as和ld。as是GNU汇编器,通常也称为GAS (GNU Assembler),ld是GNU链接器;as对GCC的输出文件进行汇编产生目标文件,然后由ld链接目标文件、重定位数据产生可执行文件。另外,GNU Binutils还包括其它一些工具:

  * addr2line用于将程序中的地址对应到文件名和相应的行号。给定一个地址和一个可执行文件,addr2line使用可执行文件中的调试信息来确定该地址所对应的文件和行号。addr2line addr -e exe -f。

  * ar用于建立、修改和提取档案文件 (archives)。档案文件经常被用作库文件,来保存程序常用的函数过程。

  * c++filt:我们知道,C++和Java中都有重载函数的特性,编译器要区分重载函数,就需要对函数标识符进行编码转换成一个汇编级别的标签 (label),这个过程称为名字改编 (name mangling) 或名字修饰 (name decoration)。而c++filt所执行的就是这个过程的逆过程。

  * dlltool用于创建Windows动态链接库。

  * gold是一种比ld更快的、但是只针对ELF文件格式的链接器。

  * nm用于列出二进制文件 (包括库文件和可执行文件) 中的符号,这些符号可以是函数、全局变量、静态变量等等。

  * objcopy用于将一种格式的目标文件复制成另外一种格式。objcopy使用GNU BFD库来读写目标文件,复制过程中要进行的转换由objcopy的命令行参数进行控制。

  * objdump用于列出关于二进制文件的各种信息。例如,可以使用它来反汇编可执行文件:objdump -D exe;可以只显示指定段 (section) 的内容:objdump -j section -s exe。

  * ranlib用于为档案文件生成索引信息,这样可以提高档案文件的访问速度。

  * readelf类似于objdump,但是它只能处理ELF格式的文件,并且没有使用GNU BFD库。

  * size用于列出目标文件或者档案文件各段的大小。

  * strings用于列出目标文件中的可打印字符串,字符串的最小长度由-n参数指定,默认为4。

  * strip用于移除目标文件中的符号,以减少程序文件的大小,这对于嵌入式系统比较有用。

  上述这些程序大部分都使用GNU BFD (Binary File Descriptor) 库,BFD库使得应用程序可以使用同样的接口来操作不同的二进制文件格式;并且这些程序很多也都使用opcodes库来汇编和反汇编机器指令。

GNU C Library   Glibc就是GNU的C标准库,主要支持GNU Hurd和Linux两种内核。Glibc是移植GNU工具链时一个不可或缺的部分。Glibc主要由两部分组成,一部分是头文件;另一部分是库的二进制文件,包括动态和静态两个版本,一般位于/lib/libc.so.6和/usr/lib/libc.a。

  另外,Glibc还有几个辅助程序运行的运行库 (C RunTime Library),分别是/usr/lib/crt1.o、/usr/lib/crti.o和/usr/lib/crtn.o,其中crt1.o中包含程序的入口函数_start以及两个未定义的符号__libc_start_main和main,由_start负责调用__libc_start_main初始化libc,然后调用我们源代码中定义的main函数;另外,由于类似于全局静态对象这样的代码需要在main函数之前执行,crti.o和crtn.o负责辅助启动这些代码。另外,Gcc中同样也有crtbegin.o和crtend.o两个文件,这两个目标文件用于配合glibc来实现C++的全局构造和析构。

  在进行嵌入式开发时,还有两种流行的C库分别是Newlib和uClibc。

图形库

阅读了Graphics in Google Chrome之后,觉得作为浏览器内核WebKit、Gecko,为了能高效美观的显示页面的内容,选择适当的图形库非常重要。如果图形库选择不当,往往会导致页面上显示的文字、图片不美观,看起来总让人觉得别扭,更为糟糕的是排列布局出现紊乱,简直无法阅览。
从浏览器发展的历史来看,IE系列浏览器的网页布局、文字图片显示的美观程度还是相当高的,也许这与Microsoft图形显示方面的功力相关,到目前为止linux桌面显示还是与传统的windows桌面显示有相当的差距。
相 比较Firefox1.5,Firefox3.0图形显示方面也有相当大的进步,这应该归功于完全采取Cario图形库来显示页面,目前应当完全达到了 IE6的显示效果。可见图形显示的好与坏,直接决定了一款浏览器的质量以及用户接受程度。那究竟什么是图形库?其主要功能是什么?目前WebKit、 Gecko可使用哪些图形库?它们在浏览器中是如何发挥其应有的作用呢?

一、图形库概述及其主要功能 A graphics library is a program designed to aid in rendering computer graphics to a monitor. This typically involves providing optimized versions of functions that handle common rendering tasks.

This can be done purely in software and running on the CPU, common in embedded systems, or being hardware accelerated by a GPU, more common in PCs. By employing these functions, a program can assemble an image to be output to a monitor. This relieves the programmer of the task of creating and optimizing these functions, and allows them to focus on building the graphics program.

目前主要的图形库有: windows提供的GDI/GDI+、DirectX、OpenGL;

支持X的有Cario、GTK、QT、OpenGL;
其他的还有Skia(google提供)、Quartz 2D(apple提供)、wxWidget等;
一 般说来图形库只提供绘画图形,渲染文字、图片等,不管是2D还是3D,其往往不提供消息处理,简单的说来就是如何高效的在一块指定的画布上将线条、文字、 图片显示出来,其中往往涉及字体、颜色等;典型的图形库如GDI/GDI+、Cario、DirectX、Quartz 2D等;
而按钮、菜单、窗口等图形组件往往是基于图形库的基础上绘画出来的并有相对固定形状,同时一般具有消息处理功能;相关实现有GTK、QT、wxWidget、windows组件等;
其中GTK、QT、wxWidget、Skia等不仅提供图形组件,同时提供图形库的功能;而Cario则是一个纯粹的图形库,类似与Quartz 2D,目前GTK2则完全基于Cario来实现;
由 于浏览器页面元素的数量存在不确定性,将页面上的一些元素对应成图形组件可能导致一个页面使用组件过多的问题(早期的IE就曾出现使用GDI对象过多的现 象)。因此尽可能的将一个页面的所有元素显示在一个图形组件上,至于其显示交给图形库来处理,其消息响应交互交给DOM及原生窗口消息循环来完成。
从这里我们可以进一步的确认图形库在浏览器中的重要性,以及随着用户需求的增加及硬件的提升,浏览器中使用3D效果应该是一个大的方向。
二、Gecko中使用图形库Cario

1、Cario概述 Cairo is a 2D graphics library with support for multiple output devices. Currently supported output targets include the X Window System, Quartz, Win32, image buffers, PostScript, PDF, and SVG file output. Experimental backends include OpenGL (through glitz), XCB, BeOS, OS/2, and DirectFB.

Cairo is designed to produce consistent output on all output media while taking advantage of display hardware acceleration when available (eg. through the X Render Extension).

其主要优点在于其在X、Win32、Quartz的基础上统一了图形库的操作方式,同时支持PS、PDF、SVG、PNG/JPEG等图像格式的输出,极大的方便页面的再次利用,在glitz的支持下支持部分3D效果。

2、Cario在Gecko中的使用 首先提供一个gfxASurface抽象类,代表一块可以作画的画布;提供一个gfxContext类,它用来管理究竟如何作画,如画圆形、旋转,维护画布的状态、当前颜色、路径等,其往往需要一个gfxASurface子类实例来初始化;

其次不同的图形输出实现不同的gfxASurface子类如gfxWindowsSurface、gfxXlibSurface、gfxQuartzSurface、gfxGlitzSurface、gfxQuartzPDFSurface、gfxPSSurface等;

其次提供一个DeviceContextImpl类实现nsIDeviceContext接口,以描述指定原生Widget相关的字体属性及创建可以在该原生Widget上作画的nsIRenderingContext接口实现;

而nsThebesRenderingContext类实现了nsIRenderingContext接口,以供外部(如不同的DOM Node页面元素对应的不同Frame)在其上显示文字、图像、作图形等;

然后当解析、布局完DOM页面元素后需要画出不同的页面元素时则由DeviceContextImpl类实例来创建nsThebesRenderingContext类实现,并初始化它,其初始化代码如下: nsThebesRenderingContext::Init(nsIDeviceContext* aContext, nsIWidget *aWidget)

{
nsThebesDeviceContext *thebesDC = static_castnsIRenderingContext接口究竟有哪些主要方法?

// RenderingContext interface

class nsIRenderingContext : public nsISupports
{
public:
.........................................................................
/**
* Initialize the RenderingContext
* @param aContext the device context to use.
* @param aWidget the widget to hook up to
* @result The result of the initialization, NS_Ok if no errors
*/
NS_IMETHOD Init(nsIDeviceContext* aContext, nsIWidget *aWidget) = 0;
/**
* Get the DeviceContext that this RenderingContext was initialized
* with. This function addrefs the device context. Though it might
* be better if it just returned it directly, without addrefing.
* @result the device context
*/
NS_IMETHOD GetDeviceContext(nsIDeviceContext *& aDeviceContext) = 0;
/**
* Sets the forground color for the RenderingContext
* @param aColor The color to set the RenderingContext to
*/
NS_IMETHOD SetColor(nscolor aColor) = 0;
/**
* Get the forground color for the RenderingContext
* @return The current forground color of the RenderingContext
*/
NS_IMETHOD GetColor(nscolor &aColor) const = 0;
/**
* Sets the font for the RenderingContext
* @param aFont The font to use in the RenderingContext
*/
NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLangGroup) = 0;
/**
* Sets the font for the RenderingContext
* @param aFontMetric The font metrics representing the
* font to use in the RenderingContext
*/
NS_IMETHOD SetFont(nsIFontMetrics *aFontMetrics) = 0;
/**
* Get the current fontmetrics for the RenderingContext
* @return The current font of the RenderingContext
*/
NS_IMETHOD GetFontMetrics(nsIFontMetrics *&aFontMetrics) = 0;
/**
* Add in a translate to the RenderingContext's transformation matrix
* @param aX The horizontal translation
* @param aY The vertical translation
*/
NS_IMETHOD Translate(nscoord aX, nscoord aY) = 0;
/**
* Add in a scale to the RenderingContext's transformation matrix
* @param aX The horizontal scale
* @param aY The vertical scale
*/
NS_IMETHOD Scale(float aSx, float aSy) = 0;
/**
* Draw a line
* @param aXO starting horiztonal coord in twips
* @param aY0 starting vertical coord in twips
* @param aX1 end horiztonal coord in twips
* @param aY1 end vertical coord in twips
*/
NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) = 0;
/**
* Draw a rectangle
* @param aRect The rectangle to draw
*/
NS_IMETHOD DrawRect(const nsRect& aRect) = 0;
/**
* Draw a string in the RenderingContext
* @param aString The string to draw
* @param aLength The length of the aString
* @param aX Horizontal starting point of baseline
* @param aY Vertical starting point of baseline.
* @param aSpacing inter-character spacing to apply
*/
NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
const nscoord* aSpacing = nsnull) = 0;
/*
* Tiles an image over an area
* @param aImage Image to tile
* @param aXImageStart x location where the origin (0,0) of the image starts
* @param aYImageStart y location where the origin (0,0) of the image starts
* @param aTargetRect area to draw to
* @param aSubimageRect the subimage (in tile space) which we expect to
* sample from; may be null to indicate that the whole image is
* OK to sample from
*/
NS_IMETHOD DrawTile(imgIContainer *aImage,
nscoord aXImageStart, nscoord aYImageStart,
const nsRect * aTargetRect,
const nsIntRect * aSubimageRect) = 0;
...............................................................................
};

其中DrawString、DrawTile方法最常用,其分别对应如何显示文字及图像。

针对图形库显示文字的基本原理可以参考Font technology and Freetype及FreeType Glyph Conventions。
至于图形库如何显示不同格式的图像可参考如gif、jpeg、png等。

Gecko对Cario的使用还体现在对canvas标签的实现,具体可参考nsCanvasRenderingContext2D.cpp、nsHTMLCanvasElement.cpp等。

三、WebKit中使用图形库 1、WebKit支持的图形库

目 前WebKit支持的图形库包括Cairo、Gtk、Qt、Wx、Cg、Mac、Skia等,虽然不同的图形库能支持不同的平台,但其在不同平台上的显示 效果也不尽相同。至于在一个指定的平台上究竟使用何种库,则显示出很大的灵活性。就目前来看,在windows平台上可选的图形库有Cairo、Qt、 Wx、Cg、Skia等,其中Graphics in Google Chrome阐述了Chrome关于图形库的选择。
其实从WebKit的角度来看,它通过提供一组与Gecko中nsIRenderingContext类似的公共图形接口,而不同的图形库则根据自身的不同实现了这些公共图形接口,以提供给WebCore元素使用,从而可以让WebKit支持不同的图形库。

2、WebKit支持不同图形库的实现

在WebKit中提供了一个GraphicsContext类,其中包括所有的图形接口,完全类似nsIRenderingContext,针对不同平台的特性,其定义中包含一些不同平台特有的
宏及元素定义。
在 目录webcore/platform/graphics/下的子目录Cairo、Cg、Gtk、Mac、Qt、Win、Wx分别提供了 GraphicsContext类部分方法的实现,而公共的实现则在webcore/platform/graphics /GraphicsContext.cpp中提供。
其中我们非常值得关注的方法有drawText与drawImage,其实现如下:

void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int from, int to)

{
if (paintingDisabled())
return;

font().drawText(this, run, point, from, to);

}
void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
{
if (paintingDisabled() || !image)
return;
float tsw = src.width();
float tsh = src.height();
float tw = dest.width();
float th = dest.height();
if (tsw == -1)
tsw = image->width();
if (tsh == -1)
tsh = image->height();
if (tw == -1)
tw = image->width();
if (th == -1)
th = image->height();
if (useLowQualityScale) {
save();
setUseLowQualityImageInterpolation(true);
}

image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op);

if (useLowQualityScale)
restore();
}

最终的实现转交给类Font、Image的方法drawText、draw来实现,而不同实现如Cairo、Cg、Gtk、Mac、Qt、Win、Wx则会 针对类Font、Image分别提供部分对应的实现,而公共的实现则在webcore/platform/graphics/Font.cpp及 Image.cpp中提供。

3、不同平台GraphicsContext实例创建及使用 GraphicsContext 创建的时机往往在对应平台的WebView获得Paint消息事件时,进而将该GraphicsContext类实例传递给FrameView及其不同的 RenderObject实例,由不同的RenderObject实例来决定究竟如何来显示自身的内容,而GraphicsContext类实例提供了各 种的显示文字、图形、图像的方法以供RenderObject实例调用。其调用关系基本上与Gecko中的不同Frame对象使用 nsIRenderingContext接口方法类似。

创建GraphicsContext实例的示例如下:

//Gtk

static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
WebKitWebViewPrivate* priv = webView->priv;
Frame* frame = core(webView)->mainFrame();
GdkRectangle clip;
gdk_region_get_clipbox(event->region, &clip);
cairo_t* cr = gdk_cairo_create(event->window);

GraphicsContext ctx(cr);

ctx.setGdkExposeEvent(event);
if (frame->contentRenderer() && frame->view()) {
frame->view()->layoutIfNeededRecursive();
if (priv->transparent) {
cairo_save(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_restore(cr);
}
frame->view()->paint(&ctx, clip);
}
cairo_destroy(cr);
return FALSE;
}
//win
void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect)
{
LOCAL_GDI_COUNTER(0, __FUNCTION__);
RECT rect = dirtyRect;
#if FLASH_BACKING_STORE_REDRAW
HDC dc = ::GetDC(m_viewWindow);
OwnPtr yellowBrush = CreateSolidBrush(RGB(255, 255, 0));
FillRect(dc, &rect, yellowBrush.get());
GdiFlush();
Sleep(50);
paintIntoWindow(bitmapDC, dc, dirtyRect);
::ReleaseDC(m_viewWindow, dc);
#endif
FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) {

GraphicsContext gc(bitmapDC);

gc.save();
gc.clip(dirtyRect);
frameView->paint(&gc, dirtyRect);
gc.restore();
}
}
//wx
void wxWebView::OnPaint(wxPaintEvent& event)
{
if (m_beingDestroyed || !m_impl->frame->view() || !m_impl->frame)
return;
wxAutoBufferedPaintDC dc(this);
if (IsShown() && m_impl->frame && m_impl->frame->document()) {
#if USE(WXGC)
wxGCDC gcdc(dc);
#endif
if (dc.IsOk()) {
wxRect paintRect = GetUpdateRegion().GetBox();
WebCore::IntSize offset = m_impl->frame->view()->scrollOffset();
#if USE(WXGC)
gcdc.SetDeviceOrigin(-offset.width(), -offset.height());
#endif
dc.SetDeviceOrigin(-offset.width(), -offset.height());
paintRect.Offset(offset.width(), offset.height());
#if USE(WXGC)
WebCore::GraphicsContext* gc = new WebCore::GraphicsContext(&gcdc);
#else
WebCore::GraphicsContext* gc = new WebCore::GraphicsContext((wxWindowDC*)&dc);
#endif
if (gc && m_impl->frame->contentRenderer()) {
if (m_impl->frame->view()->needsLayout())
m_impl->frame->view()->layout();
m_impl->frame->paint(gc, paintRect);
}
}
}
}
//Qt
void QWebFrame::render(QPainter *painter, const QRegion &clip)
{
if (!d->frame->view() || !d->frame->contentRenderer())
return;
d->frame->view()->layoutIfNeededRecursive();

GraphicsContext ctx(painter);

QVector vector = clip.rects();
WebCore::FrameView* view = d->frame->view();
for (int i = 0; i <>paint(&ctx, vector.at(i));
}
/*!
Render the frame into /a painter.
*/
void QWebFrame::render(QPainter *painter)
{
if (!d->frame->view() || !d->frame->contentRenderer())
return;
d->frame->view()->layoutIfNeededRecursive();

GraphicsContext ctx(painter);

WebCore::FrameView* view = d->frame->view();
view->paint(&ctx, view->frameGeometry());
}

4、WebKit 3D Port实现

在Clutter WebKit port中提供了WebKit 对3D Port的支持与实现,其实现类似于Gtk+/Cairo图形库的实现,但其3D效果仅实现在Port层,没有对页面上的元素如文字、图像实现3D效果支持。
这里只是简单的了解WebKit中如何整合不同的图形库及其与WebCore的交互。要想更加深入的了解页面上的文字、图形、图像究竟是如何显示出来的,则需要更进一步的针对不同平台库进行学习与了解。

WebKit 中也支持canvas标签,该标签提供的接口与Gecko能提供的几乎一致,其具体实现可参考webcore/html /CanvasRenderingContext2D.cpp,结合GraphicsContext类的实现,应该能对canvas标签的实现有充分的理 解。

四、总结

其实关于图形库及其使用的内容非常的多,而对浏览器内核来讲能对图形库进行高效使用也是非常重要的一部分,所以在这里所谈到的内容也许只是一些皮毛,但希望能在此开阔一下了解浏览器内核特别是图形库使用方面的思路。

持续

阶梯

滚动

自动化解决方案

三大子系统

自动化编译

自动化测试

自动化集成

git

svn

mock

koji