Direct2D 및 DirectWrite를 사용하여 텍스트 렌더링
GDI, GDI+ 또는 WPF와 같은 다른 API와 달리 Direct2D는 다른 API인 DirectWrite와 상호 운용되어 텍스트를 조작하고 렌더링합니다. 이 항목에서는 이러한 개별 구성 요소의 이점과 상호 운용에 대해 설명합니다.
이 항목에는 다음과 같은 섹션이 포함되어 있습니다.
Direct2D를 통해 증분 채택 가능
여러 가지 이유로 애플리케이션을 한 그래픽 API에서 다른 그래픽 API로 이동하는 것은 어려울 수 있습니다. 이는 애플리케이션 자체가 너무 커서 한 릴리스에서 새 API로 이식할 수 없거나 최신 API의 일부가 바람직하지만 이전 API가 애플리케이션의 다른 부분에서 충분히 잘 작동하기 때문에 이전 인터페이스를 사용하는 플러그 인을 지원해야 하기 때문일 수 있습니다.
Direct2D 및 DirectWrite는 별도의 구성 요소로 구현되므로 전체 2D 그래픽 시스템 또는 텍스트 부분만 업그레이드할 수 있습니다. 예를 들어 텍스트에 DirectWrite를 사용하지만 렌더링에 GDI 또는 GDI+를 사용하도록 애플리케이션을 업데이트할 수 있습니다.
Text Services 및 텍스트 렌더링
애플리케이션이 발전함에 따라 텍스트 처리 요구 사항이 점점 더 복잡해지고 있습니다. 처음에는 텍스트가 일반적으로 정적으로 배치된 UI로 제한되었고 텍스트는 단추와 같은 잘 정의된 상자에 렌더링되었습니다. 점점 더 많은 언어에서 애플리케이션을 사용할 수 있게 되면서 번역된 텍스트의 너비와 높이가 언어마다 크게 다를 수 있으므로 이 접근 방식을 유지하기가 더 어려워졌습니다. 적응하기 위해 애플리케이션은 다른 방법 대신 텍스트의 실제 렌더링 크기에 따라 UI를 동적으로 배치하기 시작했습니다.
애플리케이션이 이 작업을 완료할 수 있도록 DirectWrite는 IDWriteTextLayout 인터페이스를 제공합니다. 이 API를 사용하면 애플리케이션이 다양한 글꼴 및 글꼴 크기, 밑줄, 취소선, 양방향 텍스트, 효과, 줄임표 및 포함된 문자 모양이 아닌 문자(예: 비트맵 이모티콘 또는 아이콘)와 같은 복잡한 특성을 가진 텍스트 조각을 지정할 수 있습니다. 그러면 애플리케이션이 UI 레이아웃을 반복적으로 결정할 때 텍스트의 다양한 특성을 변경할 수 있습니다. 다음 그림과 자습서: DirectWrite 시작 항목에 표시된 DirectWrite 헬로 월드 샘플은 이러한 많은 효과를 보여 줍니다.
레이아웃은 너비에 따라 이상적으로 문자 모양을 배치하거나(WPF에서와 같이) 문자 모양을 가장 가까운 픽셀 위치(GDI와 같이)에 맞출 수 있습니다.
애플리케이션은 텍스트 측정값을 얻는 것 외에도 텍스트의 다양한 부분을 테스트할 수 있습니다. 예를 들어 텍스트의 하이퍼링크를 클릭하는 것을 알고 싶을 수 있습니다. 적중 테스트에 대한 자세한 내용은 다음을 참조하세요 .텍스트 레이아웃 항목에서 적중 횟수 테스트를 수행하는 방법.)
텍스트 레이아웃 인터페이스는 다음 다이어그램과 같이 애플리케이션에서 사용하는 렌더링 API에서 분리됩니다.
DirectWrite는 애플리케이션이 원하는 그래픽 API를 사용하여 텍스트를 렌더링하기 위해 구현할 수 있는 렌더링 인터페이스(IDWriteTextRenderer)를 제공하기 때문에 이러한 분리가 가능합니다. 애플리케이션 구현 IDWriteTextRenderer::D rawGlyphRun 콜백 메서드는 텍스트 레이아웃을 렌더링할 때 DirectWrite에 의해 호출됩니다. 그리기 작업을 수행하거나 전달하는 것은 이 메서드의 책임입니다.
문자 모양을 그리기 위해 Direct2D는 Direct2D 화면에 그리기 위해 ID2D1RenderTarget::D rawGlyphRun을 제공하고 DirectWrite는 GDI 표면으로 그리기 위해 IDWriteBitmapRenderTarget::D rawGlyphRun을 제공하여 GDI를 사용하여 창으로 전송할 수 있습니다. 편리하게, Direct2D 및 DirectWrite의 DrawGlyphRun에는 애플리케이션이 IDWriteTextRenderer에서 구현하는 DrawGlyphRun 메서드와 정확히 호환되는 매개 변수가 있습니다.
유사한 분리에 따라 텍스트 관련 기능(예: 글꼴 열거형 및 관리, 문자 모양 분석 등)은 Direct2D 대신 DirectWrite에서 처리됩니다. DirectWrite 개체는 Direct2D에서 직접 허용됩니다. 기존 GDI 애플리케이션이 DirectWrite를 활용할 수 있도록 IDWriteGdiInterop 메서드 인터페이스에 다음을 수행하는 메서드를 제공합니다.
- GDI 논리 글꼴(CreateFontFromLOGFONT)에서 DirectWrite 글꼴을 만듭니다.
- DirectWrite 글꼴 면에서 GDI 논리 글꼴로 변환합니다(ConvertFontFaceToLOGFONT).
- 선택한 글꼴에서 HDC로 DirectWrite 글꼴 얼굴을 검색합니다. (CreateFontFaceFromHdc)
- 시스템 메모리에 DirectWrite 비트맵 렌더링 대상을 만듭니다(CreateBitmapRenderTarget).
문자 모양과 텍스트 비교
텍스트는 사각형에 배치되는 다양한 스타일 한정자(글꼴, 가중치, 밑줄, 취소선 등)가 있는 유니코드 코드 포인트(문자) 집합입니다. 반면 문자 모양은 특정 글꼴 파일의 특정 인덱스입니다. 문자 모양은 렌더링할 수 있는 곡선 집합을 정의하지만 텍스트 의미는 없습니다. 문자 모양과 문자 간에 다대다 매핑이 있을 수 있습니다. 동일한 글꼴 얼굴에서 가져오고 기준선에 순차적으로 배치되는 문자 모양 시퀀스를 GlyphRun이라고 합니다. DirectWrite와 Direct2D는 모두 가장 정확한 문자 모양 렌더링 API DrawGlyphRun을 호출하며 서명이 매우 유사합니다. 다음은 Direct2D의 ID2D1RenderTarget 에서 가져옵니다.
STDMETHOD_(void, DrawGlyphRun)(
D2D1_POINT_2F baselineOrigin,
__in CONST DWRITE_GLYPH_RUN *glyphRun,
__in ID2D1Brush *foregroundBrush,
DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL
) PURE;
또한 이 메서드는 DirectWrite의 IDWriteBitmapRenderTarget에서 가져옵니다.
STDMETHOD(DrawGlyphRun)(
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
IDWriteRenderingParams* renderingParams,
COLORREF textColor,
__out_opt RECT* blackBoxRect = NULL
) PURE;
DirectWrite 버전은 기준선 원본, 측정 모드 및 문자 모양 실행 매개 변수를 유지하고 추가 매개 변수를 포함합니다.
또한 DirectWrite를 사용하면 IDWriteTextRenderer 인터페이스를 구현하여 문자 모양에 대한 사용자 지정 렌더러를 사용할 수 있습니다. 이 인터페이스에는 다음 코드 예제와 같이 DrawGlyphRun 메서드도 있습니다.
STDMETHOD(DrawGlyphRun)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
__maybenull IUnknown* clientDrawingEffect
) PURE;
이 버전에는 사용자 지정 텍스트 렌더러를 구현할 때 유용한 더 많은 매개 변수가 포함되어 있습니다. 최종 매개 변수는 애플리케이션 구현 사용자 지정 그리기 효과에 사용됩니다. (클라이언트 그리기 효과 에 대한 자세한 내용은텍스트 레이아웃에 클라이언트 그리기 효과를 추가하는 방법입니다.
각 문자 모양 실행은 원점에서 시작되며 이 원점부터 시작하는 줄에 배치됩니다. 문자 모양은 현재 월드 변환 및 연결된 렌더링 대상에서 선택한 텍스트 렌더링 설정에 의해 변경됩니다. 이 API는 일반적으로 고유한 레이아웃(예: Word Processor)을 수행하는 애플리케이션 또는 IDWriteTextRenderer 인터페이스를 구현한 애플리케이션에서만 직접 호출됩니다.
DirectWrite 및 Direct2D
Direct2D는 DrawGlyphRun을 통해 문자 모양 수준 렌더링 서비스를 제공합니다. 그러나 이를 위해서는 애플리케이션이 렌더링의 세부 정보를 구현해야 하며, 기본적으로 GDI에서 DrawText API의 기능을 자체적으로 재현합니다.
따라서 Direct2D는 문자 모양 대신 텍스트를 허용하는 API를 제공합니다. ID2D1RenderTarget::D rawTextLayout 및 ID2D1RenderTarget::D rawText. 두 메서드 모두 Direct2D 화면에 렌더링됩니다. GDI 화면에 렌더링하려면 IDWriteBitmapRenderTarget::D rawGlyphRun 이 제공됩니다. 그러나 이 메서드를 사용하려면 애플리케이션에서 사용자 지정 텍스트 렌더러를 구현해야 합니다. (자세한 내용은 다음을 참조하세요 .GDI Surface 토픽에 렌더링합니다.)
애플리케이션의 텍스트 사용은 일반적으로 간단하게 시작됩니다. 예를 들어 고정 레이아웃 단추에 확인 또는 취소를 배치합니다. 그러나 시간이 지남에 따라 국제화 및 기타 기능이 추가됨에 따라 더 복잡해집니다. 결국 많은 애플리케이션에서 DirectWrite의 텍스트 레이아웃 개체를 사용하고 텍스트 렌더러를 구현해야 합니다.
따라서 Direct2D 는 애플리케이션이 작업 코드를 백트랙하거나 중단하지 않고도 간단하게 시작하고 더 정교해질 수 있도록 하는 계층화된 API를 제공합니다. 간소화된 보기는 다음 다이어그램에 표시됩니다.
DrawText
DrawText 는 사용할 수 있는 가장 간단한 API입니다. 유니코드 문자열, 전경 브러시, 단일 형식 개체 및 대상 사각형을 사용합니다. 레이아웃 사각형 내에서 전체 문자열을 배치하고 렌더링하고 필요에 따라 클리핑합니다. 이 기능은 간단한 텍스트를 고정 레이아웃 UI에 배치할 때 유용합니다.
DrawTextLayout
IDWriteTextLayout 개체를 만들면 애플리케이션에서 텍스트 및 기타 UI 요소의 측정 및 정렬을 시작하고 여러 글꼴, 스타일, 밑줄 및 취소선이 지원됩니다. Direct2D 는 이 개체를 직접 수락하고 지정된 지점에서 텍스트를 렌더링하는 DrawTextLayout API를 제공합니다. 레이아웃 개체에서 너비와 높이를 제공합니다. Direct2D는 모든 예상 텍스트 레이아웃 기능을 구현하는 것 외에도 모든 효과 개체를 브러시로 해석하고 선택한 문자 모양 범위에 해당 브러시를 적용합니다. 인라인 개체도 호출합니다. 애플리케이션은 원하는 경우 텍스트에 문자 모양이 아닌 문자(아이콘)를 삽입할 수 있습니다. 텍스트 레이아웃 개체를 사용하는 또 다른 이점은 문자 모양 위치가 캐시된다는 것입니다. 따라서 여러 그리기 호출에 동일한 레이아웃 개체를 다시 사용하고 각 호출에 대한 문자 모양 위치를 다시 계산하지 않으면 성능이 크게 향상됩니다. GDI의 DrawText에는 이 기능이 없습니다.
DrawGlyphRun
마지막으로 애플리케이션은 IDWriteTextRenderer 인터페이스 자체를 구현하고 DrawGlyphRun 및 FillRectangle 자체 또는 다른 렌더링 API를 호출할 수 있습니다. Text Layout 개체와의 모든 기존 상호 작용은 변경되지 않은 상태로 유지됩니다.
사용자 지정 텍스트 렌더러를 구현하는 방법에 대한 예제는 사용자 지정 텍스트 렌더러를 사용하여 렌더링 항목을 참조하세요.
문자 모양 렌더링
기존 GDI 애플리케이션에 DirectWrite를 추가하면 애플리케이션이 IDWriteBitmapRenderTarget API를 사용하여 문자 모양을 렌더링할 수 있습니다. DirectWrite에서 제공하는 IDWriteBitmapRenderTarget::D rawGlyphRun 메서드는 Direct2D와 같은 추가 API를 요구하지 않고 메모리 DC에 단색으로 렌더링됩니다.
이렇게 하면 애플리케이션에서 다음과 같은 고급 텍스트 렌더링 기능을 가져올 수 있습니다.
- 하위 픽셀 ClearType을 사용하면 애플리케이션에서 문자 모양을 하위 픽셀 위치에 배치하여 선명한 문자 모양 렌더링과 문자 모양 레이아웃을 모두 허용할 수 있습니다.
- Y 방향 앤티앨리어싱을 사용하면 더 큰 문자 모양에서 곡선을 더 부드럽게 렌더링할 수 있습니다.
Direct2D로 이동하는 애플리케이션은 다음과 같은 기능도 가져옵니다.
- 하드웨어 가속.
- 방사형 그라데이션, 선형 그라데이션 및 비트맵과 같은 임의의 Direct2D 브러시로 텍스트를 채울 수 있습니다.
- PushAxisAlignedClip, PushLayer 및 CreateCompatibleRenderTarget API를 통한 계층화 및 클리핑에 대한 추가 지원
- 회색조 텍스트 렌더링을 지원하는 기능입니다. 이렇게 하면 텍스트 브러시 불투명도와 텍스트 앤티앨리어싱 모두에 따라 대상 알파 채널이 올바르게 채워집니다.
하드웨어 가속을 효율적으로 지원하기 위해 Direct2D는 알파 보정이라는 감마 수정에 약간 다른 근사치를 사용합니다. 이렇게 하면 텍스트를 렌더링할 때 Direct2D가 렌더링 대상 색 픽셀을 검사할 필요가 없습니다.
결론
이 항목에서는 Direct2D와 DirectWrite 간의 차이점과 유사성과 이를 별도의 협조적 API로 제공하기 위한 아키텍처 동기에 대해 설명합니다.