1

I am very new to Direct2D and DirectWrite and still looking into the possibilities that these APIs provide. For a potential graphics applications I was wondering whether it is possible to render text as a path so that individual points can be modified just like in a vector graphics editor. Is it possible to do something like that directly in Direct2D and DirectWrite or are there at least ways to retrieve the necessary information and construct a path object that resembles text manually?

  • Questions of this nature are generally discouraged as "too broad" here on SO, or as producing answers that will be "primarily opinion-based." That doesn't mean that it isn't a good question, though. Have you actually tried out Direct2D with respect to what you're trying to accomplish? –  Feb 14 '15 at 20:49
  • Well I am still learning to use Direct2D/DirectWrite but I find it quite difficult to use even though it seems to be a very flexible API. This link might be what I am kind of looking for but maybe a more experienced developer can comment on this. http://www.codeproject.com/Articles/376597/Outline-Text-With-DirectWrite – Karim Jordan Feb 14 '15 at 21:04
  • You might want to post your question there, under that code project. Once you reach a point where you can actually show us some code, we can assist you here. And, yes, Direct2D is a bit daunting :). –  Feb 14 '15 at 21:11

1 Answers1

3

The article you reference in your comment is correct. The key is simply IDWriteFontFace::GetGlyphRunOutline. A bit more about the usage can be found here. And the function described in that CustomTextRenderer article from their sample code is the following (ugly as it is):

//  Gets GlyphRun outlines via IDWriteFontFace::GetGlyphRunOutline
//  and then draws and fills them using Direct2D path geometries
IFACEMETHODIMP CustomTextRenderer::DrawGlyphRun(
    _In_opt_ void* clientDrawingContext,
    FLOAT baselineOriginX,
    FLOAT baselineOriginY,
    DWRITE_MEASURING_MODE measuringMode,
    _In_ DWRITE_GLYPH_RUN const* glyphRun,
    _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
    IUnknown* clientDrawingEffect)
{
    HRESULT hr = S_OK;

    // Create the path geometry.
    Microsoft::WRL::ComPtr<ID2D1PathGeometry> pathGeometry;
    hr = D2DFactory->CreatePathGeometry(&pathGeometry);

    // Write to the path geometry using the geometry sink.
    Microsoft::WRL::ComPtr<ID2D1GeometrySink> sink;
    if (SUCCEEDED(hr))
    {
        hr = pathGeometry->Open(&sink);
    }

    // Get the glyph run outline geometries back from DirectWrite 
    // and place them within the geometry sink.
    if (SUCCEEDED(hr))
    {
        hr = glyphRun->fontFace->GetGlyphRunOutline(
            glyphRun->fontEmSize,
            glyphRun->glyphIndices,
            glyphRun->glyphAdvances,
            glyphRun->glyphOffsets,
            glyphRun->glyphCount,
            glyphRun->isSideways,
            glyphRun->bidiLevel % 2,
            sink.Get());
    }

    // Close the geometry sink
    if (SUCCEEDED(hr))
    {
        hr = sink.Get()->Close();
    }

    // Initialize a matrix to translate the origin of the glyph run.
    D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
        1.0f, 0.0f,
        0.0f, 1.0f,
        baselineOriginX, baselineOriginY);

    // Create the transformed geometry
    Microsoft::WRL::ComPtr<ID2D1TransformedGeometry> transformedGeometry;
    if (SUCCEEDED(hr))
    {
        hr = D2DFactory.Get()->CreateTransformedGeometry(
            pathGeometry.Get(),
            &matrix,
            &transformedGeometry);
    }

    // Draw the outline of the glyph run
    D2DDeviceContext->DrawGeometry(
        transformedGeometry.Get(),
        outlineBrush.Get());

    // Fill in the glyph run
    D2DDeviceContext->FillGeometry(
        transformedGeometry.Get(),
        fillBrush.Get());

    return hr;
}

In that example, after creating the path geometry from the text, they are simply moving to to location specified in the x and y parameters, then tracing and filling the geometry. I call the code ugly because of the logic, especially where the sink may not get closed if the outline call fails. But it is just sample code. Good luck.

Jeff
  • 2,495
  • 18
  • 38