1. 程式人生 > >谷歌瀏覽器的源碼分析 34

谷歌瀏覽器的源碼分析 34

老師 oid nms bitblt javascrip 通過 ava web raw

通過上一次的分析,我們看到所有網頁數據經過HTML分析器之後,都會變成一個一個RenderObject對象,那麽這些RenderObject對象又是怎麽樣顯示到界面上面的呢?現在就帶著這個疑問來分析下面的代碼,這樣肯定會找到解決方法的。怎麽樣找到入口呢?其實可以先從界面顯示的類開始,可以看到顯示界面的窗口類名稱叫做Chrome_RenderWidgetHostHWND,有了這個類名稱,就可以到代碼裏查看它在那裏了。

#001 class RenderWidgetHost;

#002 class WebMouseEvent;

#003 class WebCursor;

#004

#005

typedef CWinTraits<WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>

#006 RenderWidgetHostHWNDTraits;

#007

#008 static const wchar_t* const kRenderWidgetHostHWNDClass =

#009 L"Chrome_RenderWidgetHostHWND";

可看到這個窗口類名稱是定義在這裏,再跟著kRenderWidgetHostHWNDClass來查找,就會找到顯示窗口,如下:

#001 class RenderWidgetHostHWND :

#002 public CWindowImpl<RenderWidgetHostHWND,

#003 CWindow,

#004 RenderWidgetHostHWNDTraits>,

#005 public RenderWidgetHostView {

#006 public:

#007 RenderWidgetHostHWND(RenderWidgetHost* render_widget_host);

#008 virtual ~RenderWidgetHostHWND();

#009

#010 void set_close_on_deactivate(bool close_on_deactivate) {

#011 close_on_deactivate_ = close_on_deactivate;

#012 }

#013

#014 void set_parent_hwnd(HWND parent) { parent_hwnd_ = parent; }

#015

#016 DECLARE_WND_CLASS_EX(kRenderWidgetHostHWNDClass, CS_DBLCLKS, 0);

通過上面的分析,就可以找到顯示網頁的窗口類RenderWidgetHostHWND,在這個類裏,主要顯示的位置是在void RenderWidgetHostHWND::OnPaint(HDC dc)函數裏面,它的代碼如下:

#001 void RenderWidgetHostHWND::OnPaint(HDC dc) {

#002 DCHECK(render_widget_host_->process()->channel());

#003

#004 CPaintDC paint_dc(m_hWnd);

#005 HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));

#006

#007 RenderWidgetHost::BackingStore* backing_store =

#008 render_widget_host_->GetBackingStore();

#009

#010 if (backing_store) {

#011 gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);

#012

#013 gfx::Rect bitmap_rect(

#014 0, 0, backing_store->size().width(), backing_store->size().height());

#015

#016 gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect);

#017 if (!paint_rect.IsEmpty()) {

#018 BitBlt(paint_dc.m_hDC,

#019 paint_rect.x(),

#020 paint_rect.y(),

#021 paint_rect.width(),

#022 paint_rect.height(),

#023 backing_store->dc(),

#024 paint_rect.x(),

#025 paint_rect.y(),

#026 SRCCOPY);

#027 }

......

#058 }

其實這個函數是通過如下發送消息給另一個進程進行渲染成BMP的圖片,

Send(new ViewMsg_Repaint(routing_id_, view_size));

那麽誰來接收ViewMsg_Repaint消息呢?繼續細心地查找,就到在如下類函數裏處理:

void RenderWidget::OnMsgRepaint(const gfx::Size& size_to_paint)

在這個函數,並不是最終的結果,它又會調用其它線程來處理渲染,以便達到異步的結果。它的調用過程如下:

1) RenderWidget::DoDeferredPaint() 線程裏開始渲染網頁顯示

2) RenderWidget::PaintRect() 窗口裏開始進行顯示

3) WebViewImpl::Paint() web視類開始顯示。

4) WebFrameImpl::Paint() web框架類開始顯示。

5) WebCore::ScrollView::paint() 滾動窗口顯示。

6) WebCore::Frame::paint() WebCore裏的框架顯示。

7) WebCore::RenderLayer::paint() 分層顯示。

8) WebCore::RenderLayer::paintLayer()

9) WebCore::RenderBlock::paint() 在每一層裏顯示每一塊區域。

10) WebCore::RenderBlock::paintObject() 顯示這一區域的對象。

11) WebCore::RenderBlock::paintContents() 顯示需要顯示的內容。

12) WebCore::RenderFlow::paintLines() 這裏需要顯示文字。

13) WebCore::RootInlineBox::paint() 開始顯示一行文字。

14) WebCore::InlineFlowBox::paint() 進行一行文字排列。

15) WebCore::InlineTextBox::paint()

16) WebCore::GraphicsContext::drawText() 進行一個一個文字顯示。

17) WebCore::Font::drawText() 這裏調用字體類來把文字的編碼變成位圖。

18) WebCore::Font::drawSimpleText() 這裏把位圖顯示到界面內存裏。

通過上面的分析,可以看到顯示一串文字的過程是如此復雜的過程。其它圖片顯示的過程也是一樣,都把它們變成位圖,然後再分層顯示出來。那麽JavaScript是怎麽樣顯示的呢?這個會比上面的過程更加復雜,後面再仔細地分析它。下一次,主要仔細地看看這些過程裏的一些類功能。

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

谷歌瀏覽器的源碼分析 34