728x90
본 글은 TDA3 플랫폼에서 화면에 UTF-8 인코딩 기반의 한글 문자를 표시하기 위한 Draw2D 기반의 문자 출력 작업을 단계별로 정리한 가이드입니다.
1. 기본 개념: 화면 출력 원리
- 디스플레이 출력은 픽셀 단위로 점을 찍는 방식입니다.
- 문자를 표시하려면 **글자마다 픽셀의 점 활성/비활성 상태를 갖는 font data가 필요합니다.
2. Font 데이터 생성 준비
기본적으로 제공된 Draw2D 문자 데이터는 ASCII 데이터를 기반으로 합니다.
핵심
- 한자/한글 문자를 표시하려면 글자별 Dot(점) 형태의 비트맵 데이터가 있어야 합니다.
- 이를 위해 다음 도구를 사용할 수 있습니다:
- font generator 소프트웨어
- font generator 소프트웨어
server@server-MS-7B23:~/work$ python3 font.py
한글 문자열을 입력하세요: 조
폰트 크기(px)를 입력하세요 (예: 16, 24, 32): 16
// ====================================================
// TEXT = "조"
// Font size = 16x16, 1bit, LSB-left
// ====================================================
{ "조", { 0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0x0E,0x00,0x06,0x00,0x03,0xC0,0x03,0xE0,0x07,0x38,0x1C,0x8C,0x31,0x80,0x01,0x80,0x01,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00 } },
// ASCII preview: "조"
················
················
···█████████····
·········███····
·········██·····
········██······
······████······
·····██████·····
···███····███···
··██···██···██··
·······██·······
·······██·······
·██████████████·
················
················
················
위 프로그램은 PC에서 TTF 한글/영문 폰트를 16x16 같은 고정 크기 에서 1bit 비트맵으로 변환하여, TI Draw2D에서 바로 쓸수 있게 C 배열로 변환하는 프로그램 입니다.
3. 데이터 구조 작성
UTF-8 기반 중요 포인트
- 한글은 UTF-8 인코딩에서 3바이트 사용 → 따라서 널 종료 포함하여 4바이트 형태로 처리.
- 만든 비트맵 데이터를 사용합니다.
코드 예시
#include <utils/draw2d/include/draw2d.h>
static const UInt32 gDraw2D_Font_BytesPerPixel = 2;
static const UInt32 gDraw2D_Font_CharNum = 2; /* 현재 한글 문자 개수 */
static const UInt32 gDraw2D_Font_CharWidth = 24;
static const UInt32 gDraw2D_Font_CharHeight = 24;
static const typFNT_KR24 gDraw2D_Font_KR24[] =
{
{ "조", { 0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0x0E,0x00,0x06,0x00,0x03,0xC0,0x03,0xE0,0x07,0x38,0x1C,0x8C,0x31,0x80,0x01,0x80,0x01,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00 } },
{ "준", { 0x00,0x00,0xF8,0x0F,0x00,0x0F,0xC0,0x03,0xF0,0x0F,0x1C,0x38,0x00,0x00,0x00,0x00,0xFE,0x7F,0x80,0x01,0x80,0x01,0x98,0x01,0x18,0x00,0x18,0x00,0xF8,0x1F,0x00,0x00 } },
}
};
주의:
- Index[4]는 UTF-8 3바이트 + 널 종료 구성.
- Dot 데이터는 폭×높이×bpp 계산값이며, 여기서는 24×24×2byte 기준.
4. 속성 함수 구현
Int32 Draw2D_getFontPropertyKorea24x24(Draw2D_FontProperty *pProp)
{
if(pProp == NULL)
return SYSTEM_LINK_STATUS_EFAIL;
pProp->width = gDraw2D_Font_CharWidth;
pProp->height = gDraw2D_Font_CharHeight;
pProp->addrKorea24 = (typFNT_KR24 *)gDraw2D_Font_KR24;
pProp->num = gDraw2D_Font_CharNum;
pProp->bpp = gDraw2D_Font_BytesPerPixel;
pProp->lineOffset = pProp->num * pProp->width * pProp->bpp;
pProp->colorFormat = SYSTEM_DF_BGR16_565;
return SYSTEM_LINK_STATUS_SOK;
}
주요 속성 세팅
- width, height
- 문자 수(num)
- 픽셀 포맷(colorFormat)
- 메모리 오프셋 계산(lineOffset)
5. 한글 문자열 출력 함수 구현
UInt8 *Draw2D_getKoreaFontCharAddr(Draw2D_FontProperty *font, char *c)
{
UInt16 i = 0;
if (font == NULL || c == NULL)
return NULL;
for (i = 0; i < font->num; i++)
{
if (strcmp(font->addrKorea24[i].Index, c) == 0)
{
/* 일치하는 문자 찾음 */
break;
}
}
return ((UInt8 *)font->addrKorea24 + i * sizeof(typFNT_KR24));
}
- UTF-8 문자열에 대응하는 블록 주소 반환.
- strcmp로 일치 여부 확인.
6. Draw2D를 이용한 한자 문자열 출력 함수
핵심: 문자 → 픽셀
static inline UInt32 utf8_char_bytes(const char *s)
{
unsigned char c = (unsigned char)*s;
if ((c & 0x80) == 0x00) /* 0xxxxxxx: 1바이트 (ASCII) */
return 1;
else if ((c & 0xE0) == 0xC0) /* 110xxxxx: 2바이트 */
return 2;
else if ((c & 0xF0) == 0xE0) /* 1110xxxx: 3바이트 (한글) */
return 3;
else if ((c & 0xF8) == 0xF0) /* 11110xxx: 4바이트 */
return 4;
else
return 1; /* 에러 시 기본값 */
}
Int32 Draw2D_drawKoreaString_rot(Draw2D_Handle pCtx,
UInt32 startX,
UInt32 startY,
char *str,
Draw2D_FontPrm *pPrm,
UInt32 rotate)
{
Draw2D_Obj *pObj = (Draw2D_Obj *)pCtx;
uint32_t h, w, px, py, charIndex;
uint8_t *fontAddr;
uint8_t byte, bit;
uint16_t color;
Draw2D_FontProperty font;
/* UTF-8 문자 임시 버퍼: 최대 3바이트 + '\0' */
char strTmp[4];
const char *p;
UInt32 charBytes;
/* rotate는 호환성을 위해 유지하지만 현재 미사용 */
(void)rotate;
/* 폰트 속성(폭/높이/테이블 주소 등) 세팅 */
Draw2D_getKoreaFontProperty(pPrm, &font);
/* 시작 위치가 화면 밖이면 종료 */
if (startX >= pObj->bufInfo.bufWidth)
return 0;
if (startY >= pObj->bufInfo.bufHeight)
return 0;
color = pPrm->textColor;
/* 문자열을 UTF-8 단위로 파싱하며 렌더링 */
p = str;
charIndex = 0;
while (*p != '\0')
{
/* 현재 문자의 바이트 수 계산 */
charBytes = utf8_char_bytes(p);
/* strTmp를 0으로 채워 '\0' 보장 */
memset(strTmp, 0, sizeof(strTmp));
/* UTF-8 문자 복사 (실제 바이트 수만큼만) */
memcpy(strTmp, p, charBytes);
/* 해당 글자의 폰트 구조체 시작 주소 얻기 */
fontAddr = Draw2D_getKoreaFontCharAddr(&font, strTmp);
if (fontAddr == NULL)
{
/* 폰트 테이블에 없는 문자는 건너뛰고 다음 문자로 */
p += charBytes;
charIndex++;
continue;
}
/*
* typFNT_KR16 구조체에서 Index 영역을 건너뛰고 bitmap 데이터 시작 위치로 이동.
* - Index가 char[4]라고 가정하면 sizeof(Index)=4
* - 만약 구조체 정의가 다르면 오프셋이 틀어짐(offsetof 사용이 더 안전)
*/
fontAddr += sizeof(font.addrKorea16->Index);
/* 현재 글자 출력 위치 */
px = startX + charIndex * font.width;
py = startY;
/*
* 폰트는 1bit bitmap이라고 가정:
* - width=16이면 한 줄은 16bit = 2바이트(font.width/8)
* - (font.width/8) * h 로 h번째 행의 시작 주소 계산
*/
for (h = 0; h < font.height; h++)
{
for (w = 0; w < (font.width / 8); w++)
{
/* h번째 행의 w번째 바이트 */
byte = *(fontAddr + w + (font.width / 8) * h);
/* 이 바이트가 0이면 8픽셀 모두 꺼짐 → skip */
if (byte == 0)
continue;
/*
* bit 0..7을 검사해서 켜진 픽셀만 Draw2D_drawPixel 호출
* 현재 구현은 LSB가 "왼쪽" 픽셀이라고 가정(LSB-first, left-to-right)
* 만약 폰트 데이터가 MSB-first면 (1 << (7-bit))로 바꿔야 함.
*/
for (bit = 0; bit < 8; bit++)
{
if (byte & (1 << bit)) /* ✅ LSB-left */
{
Draw2D_drawPixel(
pCtx,
px + (w * 8 + bit), /* X: 좌→우 */
py + h, /* Y: 상→하 */
color,
font.colorFormat
);
}
}
}
}
/* 다음 문자로 이동 */
p += charBytes;
charIndex++;
}
return SYSTEM_LINK_STATUS_SOK;
}
- UTF-8 문자열 길이만큼 루프 - 한글을 3바이트 영어나 특수문자는 1바이트, 다 처리 할 수 있게 바이트 수 처리하여 동작
- 각 문자 글자폭만큼 점 찍기
- 비트 검사로 채움/배경 색 결정
7. 테스트 & 확인
예제 호출:
Draw2D_drawKoreaString(handle,
stringObj->startX,
stringObj->startY,
stringObj->context, // UTF-8 문자열
&stringObj->font,
0);
- 화면에 출력 확인

참고 :
https://blog.csdn.net/AIRKernel/article/details/125503932?spm=1001.2014.3001.5501
728x90
'TI > TDA3' 카테고리의 다른 글
| I2C SLAVE MODE (0) | 2025.06.03 |
|---|---|
| Vision SDK Usecase 사용 방법 (0) | 2025.04.16 |
| CSL Example 프로그램 사용 방법 (0) | 2025.04.12 |
| TDA3-EVM PDK Build (0) | 2025.04.12 |
| mflash (0) | 2025.03.19 |