Rendering DirectWrite

Rendering Options

Text with formatting described by only an IDWriteTextFormat object can be rendered with Direct2D, however, there are a few more options for rendering an IDWriteTextLayout object.

The string described by an IDWriteTextLayout object can be rendered using the methods below.

1. Render using Direct2D

To render an IDWriteTextLayout object using Direct2D, use the ID2D1RenderTarget::DrawTextLayout method, as shown in the following code.

pRT_->DrawTextLayout(
    origin,
    pTextLayout_,
    pBlackBrush_
    );

For a more in depth look at drawing an IDWriteTextLayout object using Direct2D, see Getting Started with DirectWrite.

2. Render using a custom text renderer.

You render with a custom renderer by using the IDWriteTextLayout::Draw method, which takes a callback interface derived from IDWriteTextRenderer as an argument, as shown in the following code.

// Draw the text layout using DirectWrite and the CustomTextRenderer class.
hr = pTextLayout_->Draw(
        NULL,
        pTextRenderer_,  // Custom text renderer.
        origin.x,
        origin.y
        );

The IDWriteTextLayout::Draw method calls the methods of the custom renderer callback you provide. The DrawGlyphRun, DrawUnderline, DrawInlineObject, and DrawStrikethrough methods perform the drawing functions.

IDWriteTextRenderer declares methods for drawing a glyph run, underline, strikethrough, and inline objects. It is up to the application to implement these methods. Creating a custom text renderer allows the application to apply additional effects when rendering text, such as a custom fill or outline. A sample custom text renderer is included in the DirectWrite Hello World Sample.

3. Render ClearType to a GDI surface.

Rendering to a GDI surface is actually an example of using a custom text renderer. However, some of the work is done for you in the form of the IDWriteBitmapRenderTarget interface.

To create this interface, use the IDWriteGdiInterop::CreateBitmapRenderTarget method.

The DrawGlyphRun method of your custom text renderer calls the IDWriteBitmapRenderTarget::DrawGlyphRun method to draw the glyphs. The rendering of the underline, strikethrough, and inline objects must be done by your custom renderer.

The IDWriteBitmapRenderTarget interface renders to a device context (DC) in memory. You get a handle to this DC by using the IDWriteBitmapRenderTarget::GetMemoryDC method.

memoryHdc = g_pBitmapRenderTarget->GetMemoryDC();

Once the drawing has been performed, the memory DC of the IDWriteBitmapRenderTarget object must be copied to the destination GDI surface.

Note

You also have the option of transferring the bitmap to another type of surface, such as a GDI+ surface.

 

// Transfer from DWrite's rendering target to the window.
BitBlt(
    hdc,
    0, 0,
    size.cx, size.cy,
    memoryHdc,
    0, 0, 
    SRCCOPY | NOMIRRORBITMAP
    );

Note

Your app has the responsibility to render everything to the window in the end. This includes text and graphics. There is a performance penalty to this. Additionally, rendering to a memory DC is not GDI hardware accelerated.

 

For a more detailed overview of interoperating with GDI see Interoperating with GDI.

4. Render Grayscale Text Transparently to a GDI Surface. (Windows 8 and later)

Starting in Windows 8, you can render grayscale text transparently to a GDI surface for better performance. To do this you need to:

  1. Clear the memory DC to transparent.
  2. Render text to the memory HDC using grayscale antialiasing (DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE).
  3. Use the AlphaBlend function to render the memory HDC transparently on top of the final target HDC.
  4. Repeat as many times as necessary (say, once per glyph run) and in between other graphics may be rendered directly to the final target HDC without being overwritten by the AlphaBlend function.
pRT_->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);

pRT_->DrawTextLayout(
    origin,
    pTextLayout_,
    pBlackBrush_
    );

BLENDFUNCTION blendFunction = { 0 };  
blendFunction.BlendOp = AC_SRC_OVER;  
blendFunction.SourceConstantAlpha = 255;  
blendFunction.AlphaFormat = AC_SRC_ALPHA;

AlphaBlend(  
        hdc,  
        0, 0,  
        width, height,  
        pRT_->GetMemoryDC(),  
        0, 0,  
        width, height,  
        blendFunction  
        );

Render Using Direct2D

Render Using a Custom Text Renderer

Render to a GDI surface

Interoperating with GDI