텍스트를 화면에 출력하는 것은 단순해 보이지만, 그 이면에는 폰트 파일 파싱, 글리프 추출, 셰이핑(shaping), 래스터화, 안티 앨리어싱에 이르는 복잡한 파이프라인이 존재한다. 이 파이프라인을 어느 계층에서 다루느냐에 따라 사용하는 API와 라이브러리가 달라진다.
1. Win32 API (GDI / TextOut)
가장 전통적인 Windows 텍스트 출력 방식이다. TextOut, DrawText 같은 GDI 함수를 사용하여 디바이스 컨텍스트(DC)에 텍스트를 그린다. 폰트 제어에는 주로 두 가지 구조체가 활용된다.
LOGFONT / TEXTMETRIC / NEWTEXTMETRIC
구조체
용도
LOGFONT
폰트 생성 시 속성을 지정하는 논리 폰트 기술자. 간단한 폰트 제어에 사용한다.
TEXTMETRIC
현재 선택된 폰트의 측정 정보를 담는 구조체. LOGFONT보다 많은 정보를 제공하며 세밀한 제어가 필요할 때 사용한다. non-TrueType 폰트용이다.
NEWTEXTMETRIC
TEXTMETRIC에 네 개의 필드가 추가된 구조체. TrueType 폰트용이다.
한계
GDI 기반 텍스트 출력은 CPU 소프트웨어 래스터라이저에 의존하며, 서브픽셀 수준의 정교한 렌더링이나 OpenType 고급 타이포그래피 기능(합자, 커닝 등)을 지원하지 않는다. 해상도 독립성도 부족하여 고DPI 환경에서 품질이 저하될 수 있다.
2. DirectWrite (Windows 현대 텍스트 API)
DirectWrite는 Windows 7부터 도입된 현대적인 텍스트 레이아웃·렌더링 API로, GDI/GDI+와 Uniscribe를 대체하기 위해 설계되었다. Direct2D와 연동하면 GPU 하드웨어 가속을 활용한 텍스트 렌더링이 가능하다.
주요 특징
서브픽셀 ClearType 렌더링: LCD 디스플레이의 RGB 서브픽셀을 개별 제어하여 선명도를 높인다. 분수 픽셀 간격(fractional spacing)을 지원해 글자 배치의 균일성이 향상된다.
해상도 독립적 레이아웃: 고DPI(4K 등) 환경에서도 선명한 출력을 보장한다.
OpenType 고급 타이포그래피: 스타일 변형(stylistic alternates), 합자(ligatures), 스와시(swashes) 등 GDI에서 불가능했던 기능을 지원한다.
다국어 지원: 언어 기반 스크립트 분류, 양방향(BiDi) 텍스트, 숫자 치환 등을 지원한다.
GDI 호환 인터페이스: IDWriteGdiInterop을 통해 기존 GDI 코드와의 상호 운용이 가능하다.
컬러 폰트 지원: Windows 8.1부터 이모지 등 컬러 폰트를 지원한다.
레이어 구조
DirectWrite는 기능을 계층화하여 제공한다. 최상위 IDWriteTextLayout은 서식 있는 텍스트의 측정·렌더링·히트 테스트를 담당하고, 중간 계층은 폰트 컬렉션·열거, 하위 계층은 글리프 수준의 저수준 API로 구성된다. 렌더링 백엔드는 애플리케이션이 선택할 수 있어, Direct2D(GPU 가속), GDI 비트맵, 커스텀 렌더러 중 하나를 사용할 수 있다.
DWriteCore
Windows App SDK에 포함된 DWriteCore는 DirectWrite를 Windows 8 이상에서 사용할 수 있도록 시스템으로부터 분리한 구현이다. 크로스플랫폼 활용 가능성도 열려 있다.
참고: 2024년 기준 주요 OpenType 구현체는 세 가지로 정리된다. Windows의 DirectWrite, Apple의 CoreText, 그리고 오픈소스 진영의 FreeType + HarfBuzz 조합이다.
3. 텍스트 렌더 라이브러리
운영체제 네이티브 API를 사용하지 않고 직접 텍스트를 렌더링해야 하는 경우(크로스플랫폼 게임 엔진, 임베디드 시스템, 커스텀 UI 프레임워크 등), 전문 라이브러리를 사용한다. 이들 라이브러리는 폰트 파일을 직접 파싱하여 글리프를 추출하고, 해상도를 고려한 배율을 적용한 뒤 래스터 이미지로 변환하여 화면에 출력한다. 안티 앨리어싱도 적용하여 배경과 글자가 부드럽게 어우러지도록 한다.
현대적인 텍스트 렌더링 파이프라인은 대략 아래의 단계로 구성된다.
유니코드 문자열
→ [셰이핑] 글리프 ID + 위치 결정 (HarfBuzz)
→ [글리프 추출] 폰트에서 아웃라인 추출 (FreeType)
→ [래스터화] 벡터 → 픽셀 비트맵 변환
→ [컴포지팅] 배경과 합성하여 화면 출력 (Cairo, Skia 등)
유니코드 문자열을 올바른 글리프 ID와 위치 정보로 변환하는 텍스트 셰이핑(text shaping) 엔진
오픈 소스(MIT License), C++로 작성되어 C API를 제공
원래 FreeType, Pango, Qt의 셰이핑 코드에서 분리되어 독립 라이브러리가 되었다.
셰이핑이 필요한 이유는 유니코드 코드포인트와 실제 렌더링할 글리프 사이의 관계가 1:1이 아니기 때문이다. 예를 들어 아랍 문자는 단어 내 위치에 따라 모양이 달라지고, 합자(fi → fi)는 두 문자를 하나의 글리프로 합쳐야 한다. HarfBuzz는 폰트의 GSUB(글리프 치환)·GPOS(글리프 위치) 테이블을 분석하여 이를 처리한다.
주요 특징
OpenType, AAT(Apple Advanced Typography), SIL Graphite 등 다양한 폰트 기술 지원
Universal Shaping Engine(USE)을 통해 OpenType 명세에 개별 셰이핑 로직이 없는 스크립트도 처리
2023년부터 폰트 내에 WebAssembly 바이너리를 내장해 셰이핑 로직을 직접 정의하는 실험적 셰이퍼 지원
폰트 서브세팅 API: 문서에 필요한 글리프만 추출하여 웹·임베디드 환경에서 파일 크기를 절감
채택 현황
Android, Chrome, Firefox, Safari(WebKit), LibreOffice, Qt, GNOME, Figma, Adobe Photoshop/Illustrator/InDesign, Unreal Engine, Godot Engine 등 사실상 모든 주요 플랫폼과 소프트웨어에서 사용된다.
FreeType과 HarfBuzz는 서로를 보완한다. HarfBuzz가 "어떤 글리프를 어디에 놓을지"를 결정하면, FreeType이 그 글리프의 아웃라인을 픽셀로 변환한다. 두 라이브러리는 상호 참조 구조를 가지며, FreeType 2.14.0부터는 HarfBuzz를 동적으로 로드할 수 있어 순환 의존성 문제가 해소되었다.