Direct2D: конвертировать текст в путь

Я очень новичок в Direct2D и DirectWrite и все еще изучаю возможности, которые предоставляют эти API. Для потенциальных графических приложений мне было интересно, можно ли визуализировать текст в виде пути, чтобы отдельные точки могли быть изменены, как в редакторе векторной графики. Можно ли сделать что-то подобное непосредственно в Direct2D и DirectWrite или есть хотя бы способы извлечения необходимой информации и создания объекта пути, который напоминает текст вручную?

1 ответ

Статья, на которую вы ссылаетесь в своем комментарии, верна. Ключ просто IDWriteFontFace:: GetGlyphRunOutline. Немного больше об использовании можно найти здесь. И функция, описанная в той статье CustomTextRenderer из их примера кода, выглядит следующим образом (безобразно):

//  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;
}

В этом примере после создания геометрии пути из текста они просто перемещаются в местоположение, указанное в параметрах x и y, затем отслеживают и заполняют геометрию. Я называю код некрасивым из-за логики, особенно в тех случаях, когда приемник может не закрыться при сбое вызова схемы. Но это всего лишь пример кода. Удачи.

Другие вопросы по тегам