Direct2D教程(十)繪制文本


概述

在Direct2D中,文本的繪制是通過DirectWrite來實現的,DirectWrite實際上已經是一個獨立的DirectX組件了。關於DirectWrite,我摘錄了MSDN的一段文字。

DirectWrite介紹

當今的應用程序應提供高質量的文本渲染,分辨率無關的字體及完整的Unicode文本和布局支持,DirectWrite提供了這些功能,甚至比這更多。下面是DirectWrite的特性

  • 設備無關的文本布局系統,提高了文本的可讀性(包括文檔及UI上的文本)
  • 高質量的,子像素,ClearType文本的渲染(可以使用GDI及Direct2D或應用程序指定的渲染技術)
  • 硬件加速的文本渲染(和Direct2D一起使用時)
  • 支持多格式文本
  • 支持OpenType fonts的高級typography特性
  • 對所支持語言文本的渲染及布局。
  • GDI兼容的布局及渲染

DirectWrite API支持多格式文本的度量,繪制及命中測試。DirectWrite處理所有支持語言的文本,包括global及localized應用程序(構建於Windows7核心語言基礎之上)。DirectWrite也提供了底層的glyph渲染。

Direct2D提供了如下兩個繪制文本的函數,稍后的代碼使用第一個函數。

  • ID2D1RenderTarget::DrawText
  • ID2D1RenderTarget::DrawTextLayout

主要步驟

這里介紹的步驟都是與繪制文本相關的核心步驟,其它步驟比如創建render target或者畫刷,處理Windows消息等是每個Direct2D程序都會涉及的,這里就不再介紹了。

創建ID2D1Factory接口對象

凡事都有個根源,程序也是一樣,在Direct2D中也有一個根源對象,那就是ID2D1Factory接口,它是所有其它資源的根源,包括設備相關的資源及設備無關的資源,有了這個接口,就可以創建其它的D2D對象了,比如render target,畫刷等。所以首要任務是創建一個ID2D1Factory對象。

D2D1Factory* g_pD2DFactory = NULL;

HRESULT hr = D2D1CreateFactory(
    D2D1_FACTORY_TYPE_SINGLE_THREADED,
    &g_pD2DFactory
    );
if(FAILED(hr))
{
    MessageBox(NULL, L"Create Direct2D factory failed!", L"Error", 0);
    return;
}

創建IDWriteFactory接口對象

前面說了,在Direct2D中繪制文本實際上是通過DirectWrite來實現的,一切和文本相關的接口也都是由這個接口來創建的,所以接下來要創建一個IDWriteFactory接口對象,代碼如下。

IDWriteFactory* g_pDWriteFactory = NULL;

// Create DirectWrite Factory
hr = DWriteCreateFactory(
    DWRITE_FACTORY_TYPE_SHARED, 
    __uuidof(IDWriteFactory),
    reinterpret_cast<IUnknown**>(&g_pDWriteFactory)
    );
if(FAILED(hr))
{
    MessageBox(NULL, L"Create DirectWrite factory failed!", L"Error", 0);
    return;
}

創建IDWriteTextFormat接口對象

文本有一系列屬性,比如字體類型,Arial還是Consolas?字體大小,14px還是16px? 字體風格,傾斜或加粗?在D2D中,用IDWriteTextFormat來描述文本的這些屬性,所以,下一步需要創建IDWriteTextFormat對象了。需要注意的是文本的顏色並不是由該接口來控制的,而是由畫刷來控制。

IDWriteTextFormat* g_pTextFormat = NULL;

hr = g_pDWriteFactory->CreateTextFormat(
    L"Gabriola",                   // Font family name
    NULL,                          // Font collection(NULL sets it to the system font collection)
    DWRITE_FONT_WEIGHT_REGULAR,    // Weight
    DWRITE_FONT_STYLE_NORMAL,      // Style
    DWRITE_FONT_STRETCH_NORMAL,    // Stretch
    50.0f,                         // Size    
    L"en-us",                      // Local
    &g_pTextFormat                 // Pointer to recieve the created object
    );
if(FAILED(hr))
{
    MessageBox(NULL, L"Create IDWriteTextFormat failed!", L"Error", 0);
    return;
}

定義文本繪制區域

下一步,需要確定文本的繪制區域,也就是在哪里繪制文本,這個區域通常是一個矩形結構。所以,只需簡單定義一個rect即可。

// Create text layout rect
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_RECT_F textLayoutRect = D2D1::RectF(
    static_cast<FLOAT>(rc.left),
    static_cast<FLOAT>(rc.top),
    static_cast<FLOAT>(rc.right - rc.left),
    static_cast<FLOAT>(rc.bottom - rc.top)
    );

繪制

萬事俱備,只欠東風!下面就是最后一步也是最重要的一步,渲染文本,這里使用接口ID2D1HwndRenderTarget中的函數DrawText來完成具體的繪制工作,這個函數的具體定義如下:

virtual void DrawText(
  [in]  WCHAR *string,
  UINT stringLength,
  [in]  IDWriteTextFormat *textFormat,
  [in]  const D2D1_RECT_F *layoutRect,
  [in]  ID2D1Brush *defaultForegroundBrush,
  D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE,
  DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL
) = 0;

參數說明:

  • string,                               待繪制的文本,unicode編碼。
  • stringLength,                     文本長度。
  • textFormat,                       文本的格式化信息(屬性),上面提到過。
  • layoutRect,                        繪制區域對應的矩形。
  • defaultForegroundBrush,    繪制文本所用的畫刷

最后兩個參數暫時用不到,而且有默認參數,這里就不考慮了。調用代碼如下。

// Draw text
g_pRenderTarget->DrawText(
    wszText,           // Text to render
    cTextLength,       // Text length
    g_pTextFormat,     // Text format
    textLayoutRect,    // The region of the window where the text will be rendered
    g_pBlackBrush      // The brush used to draw the text
);

效果圖

然后呢?

這篇只是對於文本繪做一個簡單的介紹,在Direct2D與文本相關的東西遠不止這些,在后續的DirectWrite系列中會詳細闡述每個方面,敬請關注!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM