Getting Started with DirectWrite

DirectWrite is a powerful text rendering and formatting API that provides high-performance, high-quality text rendering for all applications on Windows. This guide will walk you through the fundamental steps of integrating DirectWrite into your Windows application.

Prerequisites

Before you begin, ensure you have the following:

Core Concepts

DirectWrite revolves around several key interfaces:

Step-by-Step Guide

1. Initialize the DirectWrite Factory

The first step is to create an instance of the IDWriteFactory. This is typically done once per application.


#include <dwrite.h>

IDWriteFactory* pDWriteFactory = nullptr;
HRESULT hr = DWriteCreateFactory(
    DWRITE_FACTORY_TYPE_SHARED,
    __uuidof(IDWriteFactory),
    reinterpret_cast<IUnknown**>(&pDWriteFactory)
);

if (SUCCEEDED(hr)) {
    // Factory created successfully
}
        

2. Create a Text Format

Define the appearance of your text using IDWriteTextFormat. You'll specify the font family, size, and style.


#include <dwrite.h>

IDWriteTextFormat* pTextFormat = nullptr;
PCWSTR font_name = L"Segoe UI"; // Or any other available font
FLOAT font_size = 16.0f;
PCWSTR locale_name = L"en-US";

hr = pDWriteFactory->CreateTextFormat(
    font_name,
    nullptr, // Use the system's default font collection
    DWRITE_FONT_WEIGHT_NORMAL,
    DWRITE_FONT_STYLE_NORMAL,
    DWRITE_FONT_STRETCH_NORMAL,
    font_size,
    locale_name,
    &pTextFormat
);

if (SUCCEEDED(hr)) {
    // Text format created successfully
}
        

3. Create a Text Layout

IDWriteTextLayout handles the complex task of arranging text. You'll create it with the text you want to render and its associated format.


#include <dwrite.h>

IDWriteTextLayout* pTextLayout = nullptr;
const WCHAR text[] = L"Hello, DirectWrite!";
UINT32 text_length = ARRAYSIZE(text) - 1;

// You'll need a rendering target (e.g., GDI, Direct2D) to define the layout's max width/height.
// For this example, let's assume a placeholder width.
FLOAT max_width = 600.0f;
FLOAT max_height = 300.0f;

hr = pDWriteFactory->CreateTextLayout(
    text,
    text_length,
    pTextFormat,
    max_width,
    max_height,
    &pTextLayout
);

if (SUCCEEDED(hr)) {
    // Text layout created successfully
}
        

4. Render the Text

Rendering typically involves using a drawing context (like a device context in GDI or a Direct2D device context) and a method like DrawTextLayout or by iterating through glyph runs.

The exact rendering process depends on your chosen graphics API (GDI, Direct2D, etc.). This example provides a conceptual outline.

Using GDI:


#include <dwrite.h>
#include <d2d1.h> // For D2D rendering, or use GDI
#include <gdiplus.h> // For GDI+ rendering

// Assume you have a rendering target (e.g., HDC hdc)
// ... get your HDC ...

// Use IDWriteGdiInterop for GDI rendering
IDWriteGdiInterop* pGdiInterop = nullptr;
hr = pDWriteFactory->GetGdiInterop(&pGdiInterop);

if (SUCCEEDED(hr)) {
    // Create a DWRITE_GLYPH_RUN structure
    DWRITE_GLYPH_RUN glyph_run;
    // ... populate glyph_run ...

    // Render using GDI
    // pGdiInterop->DrawGlyphRun(hdc, x, y, DWRITE_MEASURING_MODE_NATURAL, &glyph_run, ...);
}
        

Using Direct2D:

Direct2D integration is often more seamless. You'll typically draw the layout directly to a Direct2D render target.


#include <dwrite.h>
#include <d2d1.h>

// Assume you have a ID2D1RenderTarget* pRenderTarget;
// Assume you have a IDWriteTextLayout* pTextLayout;

D2D1_RECT_F layout_rect = D2D1::RectF(10.0f, 10.0f, 600.0f, 300.0f); // Position and max bounds

// Draw the text layout
// pRenderTarget->DrawTextLayout(D2D1_POINT_2F(10.0f, 10.0f), pTextLayout, pTextLayout->GetProperties().defaultTextFormat, D2D1_DRAW_TEXT_OPTIONS_NONE, D2D1_BRUSH_PROPERTIES());
        

5. Release Resources

Remember to release all DirectWrite objects when you are finished with them to avoid memory leaks.


if (pTextLayout) pTextLayout->Release();
if (pTextFormat) pTextFormat->Release();
if (pDWriteFactory) pDWriteFactory->Release();
        

Next Steps

For more detailed information and advanced techniques, refer to the DirectWrite API Reference and explore the Typography section.