Gecko使用图形库

也谈Web基特(Kit)、Gecko使用图形库

翻阅了Graphics in
GoogleChrome之后,觉得作为浏览器内核Web基特、Gecko,为了能飞速赏心悦目的显得页面的内容,接纳适用的图形库分外重大。假设图形库采取不当,往往会造成页面上出示的文字、图片不雅观,看起来总令人认为别扭,更为不佳的是排列布局出现紊乱,简直无法读书。

从浏览器发展的野史来看,IE连串浏览器的网页布局、文字图片显示的绝色程度依然一定高的,也许这与Microsoft图形显示上边的功夫相关,到最近截至linux桌面呈现仍旧与价值观的windows桌面呈现有一定的差距。

相比Firefox1.5,Firefox3.0图形突显下面也有异常大的发展,那应该归功于完全采取Cario图形库来体现页面,近日理应完全达到了
IE6的来得效果。可见图片显示的好与坏,直接控制了一款浏览器的成色以及用户接受程度。这究竟如何是图形库?其重大功效是何等?最近Web基特、
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等。

三、Web基特(Kit)中应用图形库

1、Web基特(Kit)补助的图形库

近年来Web基特(Kit)帮忙的图形库包括Cairo、Gtk、Qt、Wx、Cg、Mac、Skia等,尽管不同的图纸库能帮助不同的阳台,但其在不同平台上的来得
效果也不尽相同。至于在一个点名的阳台上究竟采纳何种库,则显示出很大的八面玲珑。就现阶段来看,在windows平台上可选的图形库有Cairo、Qt、
Wx、Cg、Skia等,其中Graphics in GoogleChrome解说了Chrome关于图形库的选取。

实在从Web基特的角度来看,它经过提供一组与Gecko中nsIRenderingContext类似的公共图形接口,而各异的图形库则按照我的不同实现了这一个集体图形接口,以提供给WebCore元素使用,从而得以让Web基特襄助不同的图形库。

2、WebKit帮忙不同图形库的贯彻

在Web基特(Kit)中提供了一个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(#ffff00);

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 WebKitport中提供了Web基特 对3D
Port的支撑与实现,其落实类似于Gtk+/Cairo图形库的贯彻,但其3D效果仅实现在Port层,没有对页面上的元素如文字、图像实现3D效果援助。

这里只是简短的了然WebKit中如何整合不同的图形库及其与WebCore的竞相。要想进一步长远的垂询页面上的文字、图形、图像究竟是什么体现出来的,则需要更进一步的对准不同平台库举办学习与了然。

Web基特中也支撑canvas标签,该标签提供的接口与Gecko能提供的几乎同一,其具体实现可参看webcore\html
\CanvasRenderingContext2D.cpp,结合GraphicsContext类的贯彻,应该能对canvas标签的落实有充足的理解。

四、总结

事实上关于图形库及其使用的内容非凡的多,而对浏览器内核来讲能对图形库举办快速使用也是特别重大的一局部,所以在此间所谈到的情节可能只是一对浮泛,但愿意能在此开展一下精晓浏览器内核特别是图形库使用方面的思路。

五、参考资源

Wiki Rendering
(computer graphics)

Wiki Cairo

Cairo HomePage

Wiki Qt

Wiki GTK+

Wiki wxWidgets

Wiki GDI

Wiki DirectX

Wiki Quartz 2D

Wiki OpenGL

Wiki OpenGL ES

Wiki gif

Wiki jpeg

Wiki png

Clutter Toolkit

Font technology and
Freetype

 


 http://hi.baidu.com/liangyj/blog/item/7693eb292be1a4f999250acc.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注