텍스트 레이아웃에 클라이언트 그리기 효과를 추가 하는 방법

Idwritetextlayout 인터페이스 및 사용자 지정 텍스트 렌더러를 사용 하 여 텍스트를 표시 하는 DirectWrite 응용 프로그램에 클라이언트 그리기 효과를 추가 하는 방법에 대 한 간단한 자습서를 제공 합니다.

이 자습서의 최종 제품은 다음 스크린샷에 표시 된 것 처럼 각에 다른 색 그리기 효과가 적용 된 텍스트 범위가 있는 텍스트를 표시 하는 응용 프로그램입니다.

"클라이언트 그리기 효과 예제"의 스크린샷 다른 색으로

참고

이 자습서는 색 텍스트를 그리는 간단한 방법의 예가 아닌 사용자 지정 클라이언트 그리기 효과를 만드는 방법에 대 한 간단한 예제입니다. 자세한 내용은 Idwritetextlayout:: SetDrawingEffect 참조 페이지를 참조 하세요.

 

이 자습서는 다음과 같은 부분으로 구성 됩니다.

1 단계: 텍스트 레이아웃 만들기

시작 하려면 Idwritetextlayout 개체가 있는 응용 프로그램이 필요 합니다. 텍스트 레이아웃이 포함 된 텍스트를 표시 하는 응용 프로그램이 이미 있거나 사용자 지정 DrawingEffect 예제 코드를 사용 하는 경우 2 단계로 건너뜁니다.

텍스트 레이아웃을 추가 하려면 다음을 수행 해야 합니다.

  1. Idwritetextlayout 인터페이스에 대 한 포인터를 클래스의 멤버로 선언 합니다.

    IDWriteTextLayout* pTextLayout_;
    
    
  2. CreateDeviceIndependentResources 메서드 끝에서 CreateTextLayout 메서드를 호출 하 여 idwritetextlayout 인터페이스 개체를 만듭니다.

    // Create a text layout using the text format.
    if (SUCCEEDED(hr))
    {
        RECT rect;
        GetClientRect(hwnd_, &rect); 
        float width  = rect.right  / dpiScaleX_;
        float height = rect.bottom / dpiScaleY_;
    
        hr = pDWriteFactory_->CreateTextLayout(
            wszText_,      // The string to be laid out and formatted.
            cTextLength_,  // The length of the string.
            pTextFormat_,  // The text format to apply to the string (contains font information, etc).
            width,         // The width of the layout box.
            height,        // The height of the layout box.
            &pTextLayout_  // The IDWriteTextLayout interface pointer.
            );
    }
    
    
  3. 마지막으로 소멸자에서 텍스트 레이아웃을 해제 해야 합니다.

    SafeRelease(&pTextLayout_);
    

2 단계: 사용자 지정 그리기 효과 클래스 구현

IUnknown에서 상속 된 메서드 외에도 사용자 지정 클라이언트 그리기 효과 인터페이스에는 구현 해야 하는 항목에 대 한 요구 사항이 없습니다. 이 경우 ColorDrawingEffect 클래스는 단순히 D2D1 _ color _ F 값을 보유 하 고,이 값을 가져오고 설정 하는 메서드와 초기에 색을 설정할 수 있는 생성자를 선언 합니다.

클라이언트 그리기 효과가 Idwritetextlayout 개체의 텍스트 범위에 적용 된 후 그리기 효과는 렌더링 될 모든 문자 모양 실행의 IDWriteTextRenderer::D rawglyphrun 메서드에 전달 됩니다. 그러면 그리기 효과의 메서드를 텍스트 렌더러에 사용할 수 있습니다.

클라이언트 그리기 효과는이 예제 보다 더 많은 정보를 제공 하 고, 문자 모양을 변경 하는 메서드를 제공 하 고, 그리기에 사용할 개체를 만드는 등의 작업을 수행 하는 것 처럼 복잡할 수 있습니다.

3 단계: 사용자 지정 텍스트 렌더러 클래스 구현

클라이언트 그리기 효과를 활용 하려면 사용자 지정 텍스트 렌더러를 구현 해야 합니다. 이 텍스트 렌더러는 Idwritetextlayout::D raw 메서드에서 그리는 문자 모양 실행에 전달 된 그리기 효과를 적용 합니다.

생성자

사용자 지정 텍스트 렌더러의 생성자는 Direct2D 개체를 만드는 데 사용 되는 ID2D1Factory 개체와 텍스트를 그릴 Direct2D 렌더링 대상을 저장 합니다.

CustomTextRenderer::CustomTextRenderer(
    ID2D1Factory* pD2DFactory, 
    ID2D1HwndRenderTarget* pRT
    )
:
cRefCount_(0), 
pD2DFactory_(pD2DFactory), 
pRT_(pRT)
{
    pD2DFactory_->AddRef();
    pRT_->AddRef();
}

DrawGlyphRun 메서드

문자 모양 실행은 클라이언트 그리기 효과를 비롯 하 여 동일한 형식을 공유 하는 문자 모양 집합입니다. DrawGlyphRun 메서드는 지정 된 문자 모양 실행에 대 한 텍스트 렌더링을 처리 합니다.

먼저 ID2D1PathGeometryID2D1GeometrySink를 만든 다음 Idwritefontface:: GetGlyphRunOutline를 사용 하 여 문자 모양 실행 개요를 검색 합니다. 그런 다음, 다음 코드와 같이 Direct2D ID2D1Factory:: CreateTransformedGeometry 메서드를 사용 하 여 기 하 도형의 원본을 변환 합니다.

HRESULT hr = S_OK;

// Create the path geometry.
ID2D1PathGeometry* pPathGeometry = NULL;
hr = pD2DFactory_->CreatePathGeometry(
        &pPathGeometry
        );

// Write to the path geometry using the geometry sink.
ID2D1GeometrySink* pSink = NULL;
if (SUCCEEDED(hr))
{
    hr = pPathGeometry->Open(
        &pSink
        );
}

// 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,
        pSink
        );
}

// Close the geometry sink
if (SUCCEEDED(hr))
{
    hr = pSink->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
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
    hr = pD2DFactory_->CreateTransformedGeometry(
        pPathGeometry,
        &matrix,
        &pTransformedGeometry
        );
}

그런 다음 Direct2D solid 브러시 개체를 선언 합니다.

ID2D1SolidColorBrush* pBrush = NULL;

ClientDrawingEffect 매개 변수가 NULL이 아닌 경우 개체에서 ColorDrawingEffect 인터페이스를 쿼리 합니다. 이 클래스는 텍스트 레이아웃 개체의 텍스트 범위에 대 한 클라이언트 그리기 효과로이 클래스를 설정 하므로 적용 됩니다.

ColorDrawingEffect 인터페이스에 대 한 포인터가 있는 경우 getcolor 메서드를 사용 하 여 저장 하는 D2D1 _ COLOR _ F 값을 검색할 수 있습니다. 그런 다음 D2D1 _ color _ F 를 사용 하 여 해당 색에 ID2D1SolidColorBrush 를 만듭니다.

ClientDrawingEffect 매개 변수가 NULL 이면 검정색 ID2D1SolidColorBrush만듭니다.

// If there is a drawing effect create a color brush using it, otherwise create a black brush.
if (clientDrawingEffect != NULL)
{
    // Go from IUnknown to ColorDrawingEffect.
    ColorDrawingEffect *colorDrawingEffect;

    clientDrawingEffect->QueryInterface(__uuidof(ColorDrawingEffect), reinterpret_cast<void**>(&colorDrawingEffect));

    // Get the color from the ColorDrawingEffect object.
    D2D1_COLOR_F color;

    colorDrawingEffect->GetColor(&color);

    // Create the brush using the color pecified by our ColorDrawingEffect object.
    if (SUCCEEDED(hr))
    {
        hr = pRT_->CreateSolidColorBrush(
            color,
            &pBrush);
    }

    SafeRelease(&colorDrawingEffect);
}
else
{
    // Create a black brush.
    if (SUCCEEDED(hr))
    {
        hr = pRT_->CreateSolidColorBrush(
            D2D1::ColorF(
            D2D1::ColorF::Black
            ),
            &pBrush);
    }
}

마지막으로, 개요 기 하 도형을 그리고 방금 만든 단색 브러시를 사용 하 여 채웁니다.

if (SUCCEEDED(hr))
{
    // Draw the outline of the glyph run
    pRT_->DrawGeometry(
        pTransformedGeometry,
        pBrush
        );

    // Fill in the glyph run
    pRT_->FillGeometry(
        pTransformedGeometry,
        pBrush
        );
}

소멸자

소멸자에서 Direct2D 팩터리 및 렌더링 대상을 해제 해야 합니다.

CustomTextRenderer::~CustomTextRenderer()
{
    SafeRelease(&pD2DFactory_);
    SafeRelease(&pRT_);
}

4 단계: 텍스트 렌더러 만들기

Createdevicedependent 리소스에서 사용자 지정 텍스트 렌더러 개체를 만듭니다. 장치에 종속 되는 ID2D1RenderTarget 을 사용 하기 때문에 장치에 따라 다릅니다.

// Create the text renderer
pTextRenderer_ = new CustomTextRenderer(
                        pD2DFactory_,
                        pRT_
                        );

5 단계: 색 그리기 효과 개체 인스턴스화

빨강, 녹색 및 파랑으로 ColorDrawingEffect 개체를 인스턴스화합니다.

// Instantiate some custom color drawing effects.
redDrawingEffect_ = new ColorDrawingEffect(
    D2D1::ColorF(
        D2D1::ColorF::Red
        )
    );

blueDrawingEffect_ = new ColorDrawingEffect(
    D2D1::ColorF(
        D2D1::ColorF::Blue
        )
    );

greenDrawingEffect_ = new ColorDrawingEffect(
    D2D1::ColorF(
        D2D1::ColorF::Green
        )
    );

6 단계: 특정 텍스트 범위에 대 한 그리기 효과 설정

Idwritetextlayou:: SetDrawingEffect 메서드 및 dwrite _ 텍스트 _ 범위 구조체를 사용 하 여 특정 텍스트 범위에 대 한 그리기 효과를 설정 합니다.

// Set the drawing effects.

// Red.
if (SUCCEEDED(hr))
{
    // Set the drawing effect for the specified range.
    DWRITE_TEXT_RANGE textRange = {0,
                                   14};
    if (SUCCEEDED(hr))
    {
        hr = pTextLayout_->SetDrawingEffect(redDrawingEffect_, textRange);
    }
}

// Blue.
if (SUCCEEDED(hr))
{
    // Set the drawing effect for the specified range.
    DWRITE_TEXT_RANGE textRange = {14,
                                   7};
    if (SUCCEEDED(hr))
    {
        hr = pTextLayout_->SetDrawingEffect(blueDrawingEffect_, textRange);
    }
}

// Green.
if (SUCCEEDED(hr))
{
    // Set the drawing effect for the specified range.
    DWRITE_TEXT_RANGE textRange = {21,
                                   8};
    if (SUCCEEDED(hr))
    {
        hr = pTextLayout_->SetDrawingEffect(greenDrawingEffect_, textRange);
    }
}

7 단계: 사용자 지정 렌더러를 사용 하 여 텍스트 레이아웃 그리기

ID2D1RenderTarget::D rawtext 또는 ID2D1RenderTarget::D Rawtextlayout 메서드 대신 idwritetextlayout::D 원시 메서드를 호출 해야 합니다.

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

8 단계: 정리

DemoApp 소멸자에서 사용자 지정 텍스트 렌더러를 해제 합니다.

SafeRelease(&pTextRenderer_);

그런 다음 클라이언트 그리기 효과 클래스를 해제 하는 코드를 추가 합니다.

SafeRelease(&redDrawingEffect_);
SafeRelease(&blueDrawingEffect_);
SafeRelease(&greenDrawingEffect_);