프로그램의 텍스트 출력 방법들
텍스트를 화면에 출력하는 것은 단순해 보이지만, 그 이면에는 폰트 파일 파싱, 글리프 추출, 셰이핑(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 등)
3-1. FreeType
- 홈페이지: https://freetype.org/
- TrueType, OpenType, Type 1, WOFF2 등 다양한 폰트 형식으로부터 글리프 정보를 추출하는 저수준 폰트 래스터라이저
- 오픈 소스(FreeType License / GPLv2)
- 최신 버전: 2.14.1 (2025년 9월 기준)
- Android의 2D 그래픽 라이브러리 Skia의 텍스트 렌더링은 FreeType을 기반으로 한다.
- 2013년 Adobe가 CFF(Compact Font Format) 렌더링 엔진을 기증하여 통합되었다.
- ClearType 관련 특허가 2019년 만료되어, 이후 버전부터 ClearType 컬러 필터링을 자유롭게 사용할 수 있다.
FreeType은 글리프를 추출하고 래스터화하는 역할을 하지만, 어떤 글리프를 어떤 순서와 위치로 배치할지(셰이핑)는 처리하지 않는다. 복잡한 스크립트(아랍어, 인도계 문자 등)를 올바르게 표시하려면 HarfBuzz 같은 셰이핑 엔진을 함께 사용해야 한다.
간단 텍스트 렌더링 예제
1) 헤더 포함
#include FT_FREETYPE_H
2) 라이브러리 초기화
error = FT_Init_FreeType(&library);
if (error) {
// 초기화 오류 처리
}
3) 폰트 페이스 로딩
error = FT_New_Face(library, "/path/to/font.ttf", 0, &face);
4) 기본적인 텍스트 렌더링
int pen_x = 300, pen_y = 200;
for (int n = 0; n < num_chars; n++) {
FT_UInt glyph_index = FT_Get_Char_Index(face, text[n]);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error) continue;
// 안티 앨리어싱 적용 비트맵으로 변환
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
if (error) continue;
// 타깃 서피스에 그리기
my_draw_bitmap(&slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top);
// 펜 위치 전진 (26.6 고정소수점 → 픽셀 변환)
pen_x += slot->advance.x >> 6;
pen_y += slot->advance.y >> 6;
}
3-2. HarfBuzz
- 홈페이지: https://harfbuzz.github.io/
- 유니코드 문자열을 올바른 글리프 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를 동적으로 로드할 수 있어 순환 의존성 문제가 해소되었다.
3-3. Pango
- 홈페이지: https://pango.gnome.org/
- 텍스트 레이아웃 및 렌더링 라이브러리로, 주로 GNOME/GTK 생태계에서 사용된다.
- 내부적으로 HarfBuzz를 셰이핑 엔진으로, FreeType을 글리프 래스터라이저로 사용한다.
- 다국어 텍스트의 방향(BiDi), 줄 바꿈, 정렬 등 고수준 레이아웃 기능을 제공한다.
- Cairo와 함께 사용하도록 설계되어 있으며
pangocairo모듈로 통합된다.
3-4. Cairo
- 홈페이지: https://cairographics.org/
- 2D 벡터 그래픽 렌더링 라이브러리
- 텍스트 처리는 내부적으로 Pango와 FreeType을 활용한다.
- X11, Wayland, Win32, macOS Quartz, OpenGL 등 다양한 백엔드를 지원하여 크로스플랫폼 그래픽이 가능하다.
간단 텍스트 렌더링 예제 (Pango + Cairo)
1) 헤더 포함
2) RAW 데이터 서피스 및 Cairo 컨텍스트 생성
cairo_surface_t *surf = cairo_image_surface_create_for_data(
buffer, CAIRO_FORMAT_ARGB32, width, height, channels * width);
cairo_t *cr = cairo_create(surf);
3) PangoLayout 생성 및 폰트·텍스트 설정
pango_layout_set_text(layout, text, -1);
PangoFontDescription *desc = pango_font_description_from_string("Sans 16");
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
4) 텍스트 렌더링
pango_cairo_show_layout(cr, layout);
// 정리
g_object_unref(layout);
cairo_destroy(cr);
cairo_surface_destroy(surf);
free(buffer);
4. 비교 요약
| Win32 GDI | DirectWrite | FreeType + HarfBuzz | Pango + Cairo | |
|---|---|---|---|---|
| 플랫폼 | Windows 전용 | Windows (DWriteCore로 크로스플랫폼 시도 중) | 크로스플랫폼 | 크로스플랫폼 |
| GPU 가속 | 없음 | Direct2D와 연동 시 가능 | 없음(래스터화만) | 없음 |
| 셰이핑 | Uniscribe | 내장 | HarfBuzz 별도 사용 | HarfBuzz 내장 |
| 고급 타이포그래피 | 제한적 | OpenType 완전 지원 | OpenType 완전 지원 | OpenType 완전 지원 |
| 사용 난이도 | 쉬움 | 보통 | 어려움(저수준) | 보통 |
| 주요 사용처 | 레거시 Win32 앱 | 현대 Windows 앱 | 게임 엔진, 임베디드 | GNOME/GTK 앱 |
5. 참고 자료
- FreeType 공식 사이트
- FreeType 튜토리얼
- HarfBuzz 공식 매뉴얼
- State of Text Rendering 2024 — 현대 텍스트 렌더링 스택 전반을 다루는 심화 문서
- DirectWrite 소개 (Microsoft Docs)
- Pango 공식 사이트
- Cairo 공식 사이트