본문 바로가기

DirectX/Direct2D,DirectWrite

Text Rendering with Direct2D and DirectWrite

https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-and-directwrite

 

Text Rendering with Direct2D and DirectWrite - Win32 apps

Unlike other APIs, such as GDI, GDI+ or WPF, Direct2D interoperates with another API, DirectWrite, to manipulate and render text. This topic describes the benefits and interoperation of these separate components.

docs.microsoft.com

 

 

GDI, GDI+ 또는 WPF와 다르게

Direct2D는 DirectWrite와 상호 동작하여 텍스트를 조작하고 그린다.



[Direct2D Enables Incremental Adoption]

 

그래픽 API를 점증적으로 변경시킬 수 있다.

 

Direct2D와 DirectWrite는 분리된 컴포넌트로 실행되기 때문에 전체를 2D로 업그레이드 하거나 텍스트 부분만 따로 할 수 있다.

예를 들어 텍스트에선 DirectWrite를 사용하도록 업그레이드를 하고 다른 렌더링 부분에서는 ※GDI나 GDI+를 계속 사용할 수 있다.

 

※ GDI(Graphics Device Interface, 그래픽 장치 인터페이스)

{

마이크로소프트 윈도우 그래픽 API

GDI는 그래픽 객체를 표시하고 모니터나 프린터와 같은 출력 장치로 전송

프레임버퍼 동기화 없이는 애니메이션을 구현할 수 없고, 3D ⁜래스터화가 부족

Direct2D와 DirectWrite가 화면 지향 렌더링을 위해 GDI를 대체해서 나왔다.

}

 

⁜래스터화(Rasterization)

{

벡터 그래픽 이미지픽셀 패턴으로 바꾸는 과정

화면위의 픽셀 하나하나로 맵핑하는 것

}


[Text Services VS Text Rendering]

 

처음에 텍스트는 정적인 UI 부분

버튼 같이 잘 정의된 영역 부분에 그려졌다.

하지만 대응해야하는 언어가 증가함에 따라 길이 높이를 언어별로 유동적으로 맞춰줘야했다.

이를 위해 어플리케이션은 실제 텍스트의 렌더사이즈에 맞춰 유동적인 레이아웃을 UI에 적용해야했다.

 

이러한 어플리케이션의 복잡한 작업을 도와주기 위해 DirectWrite는 IDWriteTextLayout 인터페이스를 제공한다.

이 API를 활용하면 다양한 글꼴 및 글꼴 크기, 밑줄, 취소 선, 양방향 텍스트, 효과, 줄임표 및  embedded non-glyph characters (비트맵 이모티콘이나 아이콘)등 복잡한 특성을 가진 텍스트를 지정할 수 있다.

 

레이아웃은 WPF처럼 너비를 기준으로 이상적으로 위치하거나 GDI처럼 가장가까운 픽셀위치에 맞춰(snap : 딱 부러지듯) 위치할 수 있다.




텍스트 레이아웃 인터페이스는 어플리케이션에서 사용하는 렌더링 API와 분리될 수 있다.

이러한 분리는 DirectWrite가 IDWriteTextRenderer라는 렌더링 인터페이스를 제공하기 때문에 가능하다. (어플리케이션에서 어떤 그래픽 API를 사용하고싶던 적용시켜준다. )

 

텍스트 레이아웃을 그릴 때 어플리케이션에서 실행되는 IDWriteTextRenderer::DrawGlyphRun 콜백 메서드는

DirectWrite에 의해서 호출된다.




glyphsDirect2D surface에 그릴 때

Direct2DID2D1RenderTarget::DrawGlyphRun를 제공한다.

 

glyphsGDI surface에 그릴 때

DirectWrite IDWriteBitmapRenderTarget::DrawGlyphRun를 제공한다.

 

IDWriteTextRenderer 실행되는 DrawGlyphRun 메서드와 Direct2D와 DirectWrite의 DrawGlyphRun 모두 서로 호환되는 매개변수를 받아들인다.




텍스트 관련 기능은 Direct2D 대신 DirectWrite에서 처리된다.

 

Direct2D에서 DirectWrite바로 이용 가능하다.

 

GDI를 사용하는 어플리케이션에서 DirectWrite를 이용하기 위해 아래와 같은 IDWriteGdiInterop 메서드들을 활용해야한다.

 - CreateFontFromLOGFONT : GDI Logical Font에서 DirectWrite Font를 생성한다.

 - ConvertFontFaceToLOGFONT : DirectWrite Font를 GDI Logical Font로 변경

 - CreateFontFaceFromHdc : 지정된 ※HDC의 현재 선택된 HFONT에 해당하는 IDWriteFontFace 개체를 만든다.

 - CreateBitmapRenderTarget : 비트맵 렌더타겟을 시스템 메모리에 생성

 

※HDC : 글꼴이 선택된 DeviceContext에 대한 핸들






[Glyphs VS Text]

 

Text

 - Unicode

 - 폰트, 굵기, 밑줄, 강조 등 stylistic modifier 존재

 - 사각형에 배열된다.

 

Glyphs

 - 특정 폰트 파일의 인덱스 존재

 - 그려질 수 있는 한 세트의 곡선들을 정의한다.

 

GlyphRun은 (1.동일한 글꼴에서 가져오고 2.기준선에서 순차적으로 배치된) glyph들의 시퀀스를 의미한다.

 

DirectWrite와 Direct2D 모두 DrawGlyphRun이라는 정밀한 glyph를 그리는 API를 호출하고 그 둘은 유사하다.

 

DrawGlyphRun의 DirectWrite 버전은 모드와 글리프 실행 매개 변수를 측정하는 기준 원점을 유지하고 추가 매개 변수가 포함되어 있다.

 

DirectWrite 를 사용하면 IDWriteTextRenderer 인터페이스 를 구현하여 글리프 용 사용자 지정 렌더러를 사용할 수도 있다.






[DirectWrite and Direct2D]

 

Direct2D는DrawGlyphRun를 통해 glyph 레벨의 렌더링을 제공한다.

하지만 GDI의 DrawText API를 기능을 재생산한 것이라 더 디테일하게 실행해야 한다.

 

그러므로 Direct2D는 

ID2D1RenderTarget::DrawTextLayout 와 ID2D1RenderTarget::DrawText라는

glyphs 대신에 text를 받아들이는

API를 제공한다.

두 메서드 모두 Direct2D surface에 그리는 메서드이다.

 

GDI surface에 그리기 위해서는 IDWriteBitmapRenderTarget::DrawGlyphRun 메서드가 제공된다.

 

어플리케이션에서 text를 사용하는 예는 고정된 버튼에 OK나 Cancel 단어를 넣을 때 사용한다. 하지만 국제화로 여러 언어를 지원하거나 다른 특성들을 넣기위해 이러한 글을 넣는 것은 복잡하게 되었다. 결국에 많은 어플리케이션이 DirectWrite의 text layout 객체를 사용하고 text를 그리게 되었다.

그러므로 Direct2D간단한 것부터 복잡한것으로 발전하는 계층적인 API를 제공한다. 이러한 계층으로 기존 작업한 코드를 버릴 필요가 없어졌다.

 

 

<DrawText>

 

- 가장 간단한 API

- Unicode string, foreground brush, 단일 format, 텍스트가 위치할 사각형을 매개변수로 받는다.

 - 고정된 UI에 간단한 text를 넣을 때 유용



<DrawTextLayout>

 

- IDWriteTextLayout 객체를 생성하여 복합적인 폰트, 스타일, 밑줄등을 제공

- Direct2D는 IDWriteTextLayout 객체를 바로 받아들일 수 있는 DrawTextLayout API를 제공한다 그리고 지정된 지점에 텍스트를 그린다.

 

-  non-glyph characters (icons)를 텍스트에 삽입할 수 있다.

 

- 텍스트 레이아웃 객체를 사용할 때 또 하나의 이점은 glyph의 위치가 캐시된다는 점이다.

- 여러번 그리는 동작이 호출될 때 같은 레이아웃 객체를 재사용하여 glyph위치를 다시 계산하는 것을 방지해 성능을 높일 수 있다.

- 이러한 기능은 GDI의 DrawText에는 없는 기능이다.

 

<DrawGlyphRun>

 

- IDWriteTextRenderer 인터페이스는 자신것이나 다른 렌더링 API의 DrawGlyphRun 와 FillRectangle 메서드를 호출한다.



 

[Glyph Rendering]

 

기존 GDI 응용 프로그램에 DirectWrite를 추가하면 응용 프로그램에서 IDWriteBitmapRenderTarget API를 사용하여 Glyph Rendering을 할 수 있다.

DirectWrite가 제공하는 IDWriteBitmapRenderTarget::DrawGlyphRun 메서드는

Direct2D같은 추가 API를 필요로하지 않고

메모리 Device Contexts에 단색으로 렌더링을 할 수 있다.

 

이를 통해 응용 프로그램은 다음과 같은 고급 텍스트 렌더링 기능을 얻을 수 있다.

 - Sub-pixel ClearType은 어플리케이션이 sub-pixel position에 glyphs를 위치시킬 수 있다. 이는 glyph 렌더링과 glyph 레이아웃 둘 모두를 sharp하게 만들어준다.

 -  Y-direction antialiasing은 더 큰 glyphs의 곡선을 더 부드럽게 그려준다.



응용 프로그램이 Direct2D를 사용하면 다음과 같은 이점들을 얻을 수 있다.

 - 하드웨어 가속

 - 방사형 그라디언트, 선형 그라디언트 및 비트 맵과 같은 Direct2D 브러시로 텍스트를 채울 수 있다.

 - PushAxisAlignedClip , PushLayer 및 CreateCompatibleRenderTarget API를 통해 layering과 clipping을 추가 지원한다.

 - The ability to support Grayscale text rendering. This correctly populates the destination alpha channel according to both the text brush opacity and the antialiasing of the text.

 

효과적으로 하드웨어 가속을 지원하기 위해 Direct2D는 alpha correction이라는 약간 다른 Gamma correction을 사용한다.

alpha correction은 텍스트를 그릴 때 Direct2D가 렌더 타겟의 컬러 픽셀을 조사하지 않아도 되게한다.




[Conclusion]

 

지금까지 주제는 Direct2D와 DirectWrite 사이의 유사점과 차이점을 설명했다.

그리고 Direct2D와 DirectWrite를 분리시키고 협동시킬 수 있는 API를 제공하는 아키텍처적 동기를 설명했다.