임베디드 환경에서 폰트 출력하기
디스플레이에 문자열을 픽셀 단위로 처리하여 출력하는 알고리즘을 개발하기 위해 먼저 각 문자별로 비트맵이 정의된 C 배열이 필요하다.
C 배열을 구하기 위해 열심히 구글링을 하던 중 굉장한 것을 찾았다.
https://www.mikroe.com/glcd-font-creator
GLCD Font Creator라는 프로그램인데, 시스템에 정의된 폰트와 스타일, 크기를 설정하면 그에 맞는 C 배열을 생성해 준다.
생성된 C 배열의 구조는 다음과 같다.
C 배열에서 각각의 줄은 줄 끝에 주석으로 설명된 문자에 해당하는 비트맵이고 순서는 아스키 코드를 따른다.
각각의 줄에서 가장 첫 번째 바이트는 개별 비트맵의 가로 픽셀 길이를 의미한다. 모든 문자의 비트맵은 가로, 세로가 고정된 고정길이로 정의되는데 (그림 예시에서는 7x15 픽셀), 가변길이로 출력하고 싶은 경우 첫 번째 바이트를 보고 비트맵의 특정 부분만 추려서 출력하면 된다.
나머지는 비트맵인데, 왼쪽 위부터 세로로 8비트씩 한 바이트이고 바이트 index는 수직 방향이 우선이다. 한 바이트의 8개 픽셀에서 가장 위쪽 픽셀이 LSB이고 아래쪽 픽셀이 MSB이다.
예를 들어 ‘a’ 문자의 경우 첫 번째 바이트인 0x06은 비트맵 중 폰트가 정의된 가로 픽셀 수를 의미하고 나머지는 다음과 같이 비트맵 데이터를 담고 있다.
따라서 byte 3의 경우 0x06이고 이 값이 배열의 5번째 바이트(index=4)에 존재하는 것을 알 수 있다.
비트맵이 정의된 C 배열을 얻었으니 이제 이 배열을 해석하여 특정 픽셀에 값을 써 주는 알고리즘을 개발하면 된다. 다음은 그 코드이다.
이 코드를 사용하기 위해서는 다음을 수정해야 한다.
LCD_WIDTH
와LCD_HEIGHT
를 타겟 디스플레이의 가로/세로 픽셀 길이로 정의draw_pixel()
함수를 각자 타겟 디스플레이에 맞는 코드로 구현
int draw_pixel(x, y, bit)
함수는 디스플레이의 왼쪽 위를 (0, 0) 좌표로 정의했을 때 (x, y) 위치에 해당하는 픽셀을 bit 값으로 설정하는 함수이다. bit는 0 또는 1이 입력된다.
이 코드의 파라미터에 대한 설명은 다음과 같다.
string
: 출력할 문자열 ('\0'
문자로 끝나는)base_x
: 문자열의 왼쪽 위 점이 위치할 디스플레이 상의 x 좌표base_y
: 문자열의 왼쪽 위 점이 위치할 디스플레이 상의 y 좌표font
: 앞에서 GLCD font creator를 통해 생성한 C 배열width
: 폰트의 가로 픽셀 길이height
: 폰트의 세로 픽셀 길이start
폰트에 정의된 시작 문자의 아스키 코드end
: 폰트에 정의된 끝 문자의 아스키 코드spacing
: 자간line_spacing
: 줄 간격monospace
: 1이면 고정길이 출력 0이면 가변길이 출력
파라미터가 많은데, 기존 코드에서는 구조체를 통해 함수를 호출하도록 하였으나 설명을 위해 하나하나 풀어서 작성하였다.
width
, height
는 폰트의 가로 및 세로 픽셀 수이다. GLCD font creator에서 생성하는 C 배열은 가변길이 폰트라도 크기가 가장 큰 문자를 기준으로 가로 및 세로 픽셀 수가 모든 문자에 대해 고정으로 정의된다. (빈 부분의 픽셀 값은 0)
start
, end
의 경우 GLCD font creator에서 C 배열을 생성할 때 메모리 절약을 위해 사용하지 않는 아스키 코드 구간을 삭제하고 비트맵을 생성하도록 설정할 수 있는데, 여기서 생성하도록 설정된 아스키 코드 구간의 첫 문자가 start
이고, 마지막 문자가 end
이다.
기본 설정의 경우 32 ~ 127 구간의 C 배열을 생성하므로 start=32
, end=127
을 지정하면 된다.
spacing
, line_spacing
: 자간과 줄간격도 설정할 수 있도록 구현하였다.
monospace
: 가변길이 문자열을 고정길이로 출력할 경우 어색하기 때문에 monospace
파라미터를 사용하여 어떤 방식으로 출력할지 설정하도록 하였다.
위 함수의 사용 예는 다음과 같다.