在 LCD 上显示字符
原始方式:取模显示字符
LCD显示字符方法
-
通过字符取模,在LCD屏上显示字符
-
字符取模生成字符点阵,表示哪些像素点填充颜色
字符点阵表示
-
字符点阵用二维数组表示,每个小方块对应一个bit位
- 字符点阵图
-
例子:宽64,高86的字符点阵,用unsigned char arr[86][8]表示
-
就是一个 86 行 8 列的 unsigned char 类型数组
-
字符点阵中的每一个小方块对应一个 bit 位,因为一行一共有 64 个小方块、也就对应 8 个字节(8 * 8 = 64
-
字符取模软件
-
使用软件获取字符的子模,在LCD屏上显示
-
简单但不适用于复杂应用
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>
#define FB_DEV "/dev/fb0" //LCD设备节点
static int width; //LCD宽度
static int height; //LCD高度
static unsigned short *screen_base = NULL;//LCD显存基地址
static unsigned char ch_char1[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0xFF,0xFF,0xFF,0x01},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0x00,0xFC,0x07,0xC0,0x7F,0x00,0x00,0x00},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"正",0*/
};
static unsigned char ch_char2[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x07,0x00,0x00,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0x01,0x00,0x00,0xC0,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00},
{0x00,0x01,0x00,0x00,0xC0,0x00,0x7C,0x00},
{0x00,0x0F,0x00,0x03,0xF8,0x00,0x7F,0x00},
{0x80,0x3F,0xF0,0x03,0xFF,0x81,0xFF,0x00},
{0x80,0xFF,0xFC,0x03,0xFE,0x81,0xFF,0x00},
{0xC0,0x7F,0xFC,0x07,0xFE,0x03,0xFF,0x01},
{0xC0,0x7F,0xF8,0x07,0xFC,0x03,0xFF,0x01},
{0xE0,0x3F,0xF8,0x0F,0xFC,0x07,0xFE,0x01},
{0xE0,0x3F,0xF0,0x0F,0xFC,0x07,0xFE,0x03},
{0xF0,0x1F,0xF0,0x0F,0xF8,0x07,0xFE,0x03},
{0xF0,0x1F,0xF0,0x1F,0xF8,0x0F,0xFC,0x07},
{0xF8,0x0F,0xE0,0x1F,0xF8,0x0F,0xFC,0x07},
{0xF8,0x0F,0xE0,0x1F,0xF0,0x0F,0xF8,0x0F},
{0xFC,0x07,0xE0,0x3F,0xF0,0x1F,0xF8,0x0F},
{0xFC,0x07,0xE0,0x3F,0xF0,0x1F,0xF0,0x1F},
{0xFC,0x03,0xC0,0x0F,0xE0,0x03,0xF0,0x07},
{0xF0,0x03,0xC0,0x00,0x60,0x00,0xE0,0x01},
{0xE0,0x01,0x00,0x00,0x00,0x00,0x20,0x00},
{0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"点",1*/
};
static unsigned char ch_char3[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x80,0x7F,0x00,0x80,0xFF,0x00,0x00,0x00},
{0x80,0x7F,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x80,0x7F,0x00,0xC0,0x7F,0x00,0x00,0x00},
{0x80,0x7F,0x00,0xC0,0x3F,0x00,0x00,0x00},
{0x80,0x7F,0x00,0xE0,0x3F,0x00,0x00,0x00},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0x80,0x7F,0xF8,0x07,0x00,0x00,0xFE,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x7F,0xF8,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0x3F,0x00,0x00,0xFC,0x07,0x06,0x00},
{0xC0,0x3F,0x80,0x00,0xFC,0x07,0x07,0x00},
{0xC0,0x3F,0x80,0x03,0xFC,0x87,0x0F,0x00},
{0xE0,0x3F,0xC0,0x07,0xFC,0xE7,0x1F,0x00},
{0xE0,0x3F,0xE0,0x1F,0xFC,0xF7,0x3F,0x00},
{0xE0,0x3F,0xF0,0x3F,0xFC,0xE7,0x7F,0x00},
{0xE0,0x1F,0xF0,0x3F,0xFC,0xE7,0xFF,0x00},
{0xF0,0x1F,0xF8,0x1F,0xFC,0xC7,0xFF,0x00},
{0xF0,0x1F,0xFC,0x0F,0xFC,0x87,0xFF,0x01},
{0xF0,0x1F,0xFE,0x0F,0xFC,0x07,0xFF,0x03},
{0xF0,0x1F,0xFF,0x07,0xFC,0x07,0xFF,0x07},
{0xF8,0x8F,0xFF,0x03,0xFC,0x07,0xFE,0x0F},
{0xF8,0x8F,0xFF,0x01,0xFE,0x07,0xFC,0x0F},
{0xFC,0xCF,0xFF,0xFF,0xFF,0x07,0xF8,0x1F},
{0xFC,0xE7,0xFF,0xFE,0xFF,0x07,0xF8,0x0F},
{0xFE,0xC7,0x7F,0xFE,0xFF,0x03,0xF0,0x07},
{0xFE,0x83,0x3F,0xFC,0xFF,0x03,0xE0,0x03},
{0xF8,0x03,0x1F,0xFC,0xFF,0x03,0xE0,0x00},
{0xF0,0x03,0x0E,0xFC,0xFF,0x01,0x40,0x00},
{0xE0,0x01,0x04,0xFC,0xFF,0x00,0x00,0x00},
{0xC0,0x00,0x00,0xFC,0x3F,0x00,0x00,0x00},
{0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"原",2*/
};
static unsigned char ch_char4[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
{0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x00},
{0x00,0x00,0x00,0x00,0x00,0xFF,0x3F,0x00},
{0x00,0x00,0x00,0x00,0xC0,0xFF,0x1F,0x00},
{0x00,0x00,0x00,0x00,0xF0,0xFF,0x07,0x00},
{0x00,0x00,0x00,0x00,0xF8,0xFF,0x03,0x00},
{0x00,0x00,0x00,0x00,0xFE,0xFF,0x00,0x00},
{0x00,0x00,0x00,0x80,0xFF,0x7F,0x00,0x00},
{0x00,0x00,0x00,0xC0,0xFF,0x1F,0x00,0x00},
{0x00,0x00,0x00,0xF0,0xFF,0x07,0x00,0x00},
{0x00,0x00,0x00,0xF8,0xFF,0x03,0x00,0x00},
{0x00,0x00,0x00,0xF8,0xFF,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x0F,0x00,0x00,0x00},
{0x00,0x10,0x00,0xFE,0x0F,0x00,0x00,0x00},
{0x00,0xF0,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0xF0,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0xE0,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0xE0,0xFF,0xFF,0x07,0x00,0x00,0x00},
{0x00,0xE0,0xFF,0xFF,0x07,0x00,0x00,0x00},
{0x00,0xE0,0xFF,0xFF,0x03,0x00,0x00,0x00},
{0x00,0xC0,0xFF,0xFF,0x01,0x00,0x00,0x00},
{0x00,0xC0,0xFF,0xFF,0x00,0x00,0x00,0x00},
{0x00,0xC0,0xFF,0x3F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"子",3*/
};
#define argb8888_to_rgb565(color) ({ \
unsigned int temp = (color); \
((temp & 0xF80000UL) >> 8) | \
((temp & 0xFC00UL) >> 5) | \
((temp & 0xF8UL) >> 3); \
})
/********************************************************************
* 函数名称: lcd_draw_character
* 功能描述: 在LCD屏指定位置处(x, y)画字符, 参数color指定字符的颜色
指针ch指向字符对应的子模数组、参数w、h分别表示字符的宽度和高度
* 输入参数: color
* 返 回 值: 无
********************************************************************/
static void lcd_draw_character(unsigned int x, unsigned int y,
const unsigned char *ch, unsigned int w,
unsigned int h, unsigned int color)
{
unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
unsigned long temp;
unsigned int end_x, end_y;
int j;
int columns;
/**
计算出二维数组有多少列
参数w表示的是字符的宽度,1个宽度表示的是1个bit位
并不是一个字节,这里要注意,如果宽度不是byte单位的整数倍
通常会补零
**/
columns = w / 8; //1byte=8bit
if (0 != w % 8) columns++;
/* 对参数进行限定 */
if (w < 1 || h < 1) return;
if (x >= width || y >= height) return;
/* 计算出结束坐标位置 */
end_x = x + w - 1;
end_y = y + h - 1;
/* 对结束坐标位置进行限定 */
if (end_x >= width)
end_x = width - 1;
if (end_y >= height)
end_y = height - 1;
/* 计算有效宽度 */
h = end_y - y + 1;
w = end_x - x + 1;
/* 打点 */
temp = y * width + x; //定位到起点
for (y = 0; y < h; y++, temp += width) {
for (x = 0, j = 0; x < w; ) { // 对字符的宽度进行循环
// 判断当前位是否需要绘制,如果需要则将对应显存位置的像素设置为指定的颜色
// *(ch + y * columns + j) 取得点阵图数据中对应位置的一个字节
// x % 8 取得当前像素在字节中的位置(0到7)
// 0x1 << (x % 8) 将1左移 (x % 8) 位,以便生成一个掩码,用于检测当前像素在字节中的位置
// 通过按位与操作,检查当前字节的相应位是否为1。
// 如果当前位为1,则表示在点阵图中该位置需要绘制,否则不绘制
if (*(ch + y * columns + j) & (0x1 << (x % 8)))
screen_base[temp + x] = rgb565_color;
x++;// 移动到下一个像素
if (0 == x % 8) j++; // 每移动8个像素,j递增1,表示到下一个字节
}
}
}
int main(void)
{
struct fb_var_screeninfo fb_var = {0};
struct fb_fix_screeninfo fb_fix = {0};
unsigned long screen_size;
int fd;
/* 打开framebuffer设备 */
fd = open(FB_DEV, O_RDWR);
if (0 > fd) {
fprintf(stderr, "open error: %s: %s\n", FB_DEV, strerror(errno));
exit(EXIT_FAILURE);
}
/* 获取framebuffer设备信息 */
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
screen_size = fb_fix.line_length * fb_var.yres;
width = fb_var.xres;
height = fb_var.yres;
/* 内存映射 */
screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (MAP_FAILED == (void *)screen_base) {
perror("mmap error");
close(fd);
exit(EXIT_FAILURE);
}
/* LCD背景刷白 */
memset(screen_base, 0xFF, screen_size);
/* 显示字符 */
int x = width * 0.5 - 128; // 计算字符“正”在LCD屏幕上的X坐标,将字符中心对齐到屏幕水平中心位置,并向左偏移128像素
int y = height * 0.5 - 43; // 计算字符“正”在LCD屏幕上的Y坐标,将字符中心对齐到屏幕垂直中心位置,并向上偏移43像素
lcd_draw_character(x, y, (unsigned char *)ch_char1, 64, 86, 0xFF00FF); // 画字符“正”
lcd_draw_character(x + 64, y, (unsigned char *)ch_char2, 64, 86, 0xFF00FF);
lcd_draw_character(x + 128, y, (unsigned char *)ch_char3, 64, 86, 0xFF00FF);
lcd_draw_character(x + 192, y, (unsigned char *)ch_char4, 64, 86, 0xFF00FF);
/* 退出程序 */
munmap(screen_base, screen_size);
close(fd);
return 0;
}
-
大致流程
-
初始化并打开framebuffer设备
-
获取设备的分辨率信息和显存地址
-
清空屏幕,设置背景颜色
-
在指定位置绘制字符
-
清理资源并退出程序
-
-
执行测试程序
操作系统字体文件
-
字体文件存储字符的位图数据
-
常见字体文件格式:otf、ttf、ttc等
- Linux 系统中,字体文件通常会放在/usr/share/fonts 目录下,有了字体文件之后,我们就不需要再对字符
进行取模了,它们已经编码进了字体文件中,我们只需要解析字体文件、访问字体文件,从字体文件中读取
出字符的位图数据即可
- Linux 系统中,字体文件通常会放在/usr/share/fonts 目录下,有了字体文件之后,我们就不需要再对字符
-
使用开源字体引擎(如freetype)解析字体文件,读取字符位图数据
freetype 简介
FreeType 是一个开源的字体引擎库
该库设计小巧、高效、高度可定制且可移植
提供了统一的接口来访问多种不同格式的字体文件
接口简单、易用,简化了访问字体文件内容的任务
FreeType 也称为 “FreeType 2”,区别于已弃用的 “FreeType 1”,FreeType 1 库已不再维护和支持
freetype 移植
下载 FreeType 源码
-
下载链接 https://download.savannah.gnu.org/releases/freetype/
- 选择 freetype-2.8.tar.gz 压缩文件
交叉编译 FreeType 源码
-
在 tools 目录下创建一个名为 freetype 的目录,把它作为 FreeType 的安装目录
-
tar -xzf freetype-2.8.tar.gz
-
关于FreeType库的一些特点和使用方法
-
FreeType库采用模块化设计,可以根据需要裁剪功能模块,以减小库文件的大小
-
FreeType库提供了多个配置选项,可以进行自定义配置或裁剪
-
可以参考FreeType源码目录下的docs/CUSTOMIZE文档,详细了解如何进行配置和裁剪
-
建议查看其他说明文档,如docs目录下的其他文档,以获取更多信息
-
简单地配置一下
-
vi include/freetype/config/ftoption.h
-
打开以下两个配置宏
- #define FT_CONFIG_OPTION_SYSTEM_ZLIB
#define FT_CONFIG_OPTION_USE_PNG
- #define FT_CONFIG_OPTION_SYSTEM_ZLIB
-
-
-
对 FreeType 工程源码进行配置
-
./configure --prefix=/home/alientek/tools/freetype/ --host=arm-poky-linux-gnueabi --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS=“-I/home/alientek/tools/zlib/include -L/home/alientek/tools/zlib/lib” ZLIB_LIBS=-lz LIBPNG_CFLAGS=“-I/home/alientek/tools/png/include -L/home/alientek/tools/png/lib” LIBPNG_LIBS=-lpng
-
-prefix 选项指定 FreeType 库的安装目录
-
–host 选项设置为交叉编译器名称的前缀
-
–with-zlib=yes 表示使用 zlib
-
–with-bzip2=no 表示不使用 bzip2 库
-
…
-
ZLIB_CFLAGS 选项用于指定 zlib 的头文件路径和库文件路径,根据实际安装路径填写
-
ZLIB_LIBS 选项指定链接的 zlib 库的名称
-
LIBPNG_CFLAGS 选项用于指定 libpng 的头文件路径和库文件路径,根据实际安装路径填写
-
LIBPNG_LIBS 选项用于指定链接的 libpng 库的名称
-
-
make 编译
-
make install 安装
安装目录下的文件
-
同样有 bin 目录、include 目录以及 lib 目录
-
在应用程序源码中需要包含include/freetype2目录下的ft2build.h头文件,还需要包含一个名为FT_FREETYPE_H的宏定义头文件,实际上就是include/freetype2/freetype/freetype.h头文件
- 在应用程序中通常会这样写:
#include <ft2build.h>
#include FT_FREETYPE_H
- 在应用程序中通常会这样写:
移植到开发板
-
删除原有的 FreeType 库文件
- m -rf /usr/lib/libfreetype.*
-
编译得到的库文件拷贝到开发板/usr/lib 目录下
freetype 库的使用
资料
-
FreeType 官方
- https://www.freetype.org/freetype2/docs/tutorial/step1.html
https://www.freetype.org/freetype2/docs/tutorial/step2.html
https://www.freetype.org/freetype2/docs/reference/index.html
- https://www.freetype.org/freetype2/docs/tutorial/step1.html
-
中文参考资料
- https://www.doc88.com/p-7178359224563.html?r=1
基础概念
-
字形(glyph):字符的不同书写风格,如宋体和微软雅黑的“国”
-
字形索引:通过字符编码(如 ASCII、Unicode)转换得到
-
像素点(pixel)、点(point)以及 dpi
-
像素点:
LCD 分辨率为 800*480 表示水平方向有 800 个像素点,垂直方向有 480 个像素点 -
“点”(point):
点是物理单位,一个点等于 1/72 英寸(1 英寸等于 25.4 毫米) -
dpi(dots per inch):
dpi 表示每英寸的像素点数,如 300*400dpi 表示水平方向每英寸有 300 个像素点,垂直方向有 400 个像素点 -
像素点数计算公式:
-
像素点数 = 点数 * dpi / 72。
- 计算示例:
假设设备水平 dpi 为 300,点数为 50,则像素点数为 50 * 300 / 72 = 208
-
字形布局
-
用图描述,原点和基准线用于定位字形
-
水平布局
-
垂直布局
-
-
基准线和原点
-
水平布局和垂直布局都有一个原点(origin)
-
水平线(X轴)和垂直线(Y轴)称为基准线
-
水平布局:垂直基线在字形左边
-
垂直布局:水平基线在字形上方
-
-
字形的定位
-
原点和基准线用于定位字形
-
不同布局方式使用不同的约束来放置字形
-
-
字形的宽度和高度
-
每个字形有自己的宽度(width)和高度(height)
-
不同字符的字形宽高可能不同
-
-
bearingX 和 bearingY
-
bearingX:从垂直基线到字形轮廓最左边的距离
-
bearingY:从水平基线到字形轮廓最上边的距离
-
-
xMin/xMax、yMin/yMax
-
xMin 和 xMax 表示字形轮廓的左右边界
-
yMin 和 yMax 表示字形轮廓的上下边界
-
这些参数构成字形的边界框(bounding box)
-
-
advance
-
表示步进宽度,即相邻两个原点位置的距离
-
水平布局:advanceX
-
垂直布局:advanceY
-
-
字形的位图数据
-
FreeType 访问字体文件获取字形的位图数据
-
位图数据存储在 buffer 中,每个点用一个字节表示
-
-
字符显示的对齐
-
字符显示时通过水平基线和垂直基线保证对齐
-
不同字符的基线到轮廓的距离不同
-
水平基线用于垂直方向对齐,垂直基线用于水平方向对齐
-
-
绘制字符时的定位
-
通过 bearingX 和 bearingY 确定字符显示的左上角位置
-
例:原点 (100, 100),字符左上角位置为 (100+bearingX, 100-bearingY)
-
初始化 FreeType 库
-
在使用 FreeType 库函数之前,必须进行初始化
-
FT_Init_FreeType() 函数
-
定义一个 FT_Library 类型变量
-
调用 FT_Init_FreeType() 函数并传递该变量的指针作为参数
-
-
使用示例
- FT_Library library;
FT_Error error;
error = FT_Init_FreeType(&library);
if (error)
fprintf(stderr, “Error: failed to initialize FreeType library object\n”);
- FT_Library library;
-
FT_Init_FreeType() 的操作
-
创建一个 FreeType 库对象
-
返回值:成功返回 0,失败返回非零值错误码
-
加载 face 对象
-
使用 FT_New_Face() 函数创建一个新的 face 对象,加载字体文件
- 调用 FT_New_Face()函数前,我们需要定义一个 FT_Face 类型变量,使用示例如下所示:
FT_Library library; //库对象的句柄
FT_Face face; //face 对象的句柄
FT_Error error;
FT_Init_FreeType(&library);
error = FT_New_Face(library, “/usr/share/fonts/font.ttf”, 0, &face);
if (error) {
/* 发生错误、进行相关处理 */
}
- 调用 FT_New_Face()函数前,我们需要定义一个 FT_Face 类型变量,使用示例如下所示:
-
face 对象的定义
- face 描述了特定的字体样式和风格
-
FT_New_Face() 函数原型
-
FT_Error FT_New_Face(FT_Library library, const char *filepathname,
FT_Long face_index, FT_Face *aface);-
library:FreeType 库对象的句柄
-
filepathname:字库文件路径名
-
face_index:索引,指示要加载的 face,通常设置为 0
-
aface:指向新建 face 对象的指针,失败时值为 NULL
-
返回值:
调用成功返回 0。
失败返回非零值错误码
-
-
设置字体大小
-
设置字体的大小有两种方式:FT_Set_Char_Size()和 FT_Set_Pixel_Sizes()
-
FT_Set_Pixel_Sizes() 函数
-
用于设置字体的宽度和高度,以像素为单位
-
示例:
FT_Set_Pixel_Sizes(face, 50, 50);-
第一个参数:face 句柄
-
第二个参数和第三个参数:字体的宽度和高度,以像素为单位
-
-
设置为 0 的参数
-
可以将宽度或高度中的任意一个参数设置为 0
-
设置为 0 的参数将等于另一个参数的值
-
FT_Set_Pixel_Sizes(face, 50, 0);
- 字体高度设置为 0,意味着字体高度将等于字体宽度 50
-
-
-
FT_Set_Char_Size()函数
-
用于设置字体大小
-
示例:
error = FT_Set_Char_Size(
face, // face 对象的句柄
1664, // 以 1/64 点为单位的字体宽度
1664, // 以 1/64 点为单位的字体高度
300, // 水平方向上每英寸的像素点数
300 // 垂直方向上每英寸的像素点数
);
// 垂直方向上每英寸的像素点数
);-
宽度和高度以 1/64 点为单位,一个点是 1/72 英寸
-
宽度或高度可以设置为 0,表示该参数将等于另一个参数的值
-
dpi 参数设置为 0 时,表示使用默认值 72dpi
-
-
加载字形图像
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h> //数学库函数头文件
#include <wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define FB_DEV "/dev/fb0" //LCD设备节点
#define argb8888_to_rgb565(color) ({ \
unsigned int temp = (color); \
((temp & 0xF80000UL) >> 8) | \
((temp & 0xFC00UL) >> 5) | \
((temp & 0xF8UL) >> 3); \
})
static unsigned int width; //LCD宽度
static unsigned int height; //LCD高度
static unsigned short *screen_base = NULL;//LCD显存基地址 RGB565
static unsigned long screen_size;
static int fd = -1;
static FT_Library library;
static FT_Face face;
static int fb_dev_init(void)
{
struct fb_var_screeninfo fb_var = {0};
struct fb_fix_screeninfo fb_fix = {0};
/* 打开framebuffer设备 */
fd = open(FB_DEV, O_RDWR);
if (0 > fd) {
fprintf(stderr, "open error: %s: %s\n", FB_DEV, strerror(errno));
return -1;
}
/* 获取framebuffer设备信息 */
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
screen_size = fb_fix.line_length * fb_var.yres;
width = fb_var.xres;
height = fb_var.yres;
/* 内存映射 */
screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (MAP_FAILED == (void *)screen_base) {
perror("mmap error");
close(fd);
return -1;
}
/* LCD背景刷成黑色 */
memset(screen_base, 0xFF, screen_size);
return 0;
}
static int freetype_init(const char *font, int angle)
{
FT_Error error; //存储FreeType库函数的返回值
FT_Vector pen; //表示绘制文本时的起点位置
FT_Matrix matrix;//表示变换矩阵
float rad; //旋转角度
/* FreeType初始化 */
FT_Init_FreeType(&library);
/* 加载face对象 */
error = FT_New_Face(library, font, 0, &face);
if (error) {
fprintf(stderr, "FT_New_Face error: %d\n", error);
exit(EXIT_FAILURE);
}
/* 原点坐标 */
pen.x = 0 * 64;
pen.y = 0 * 64; //原点设置为(0, 0)
/* 2x2矩阵初始化 */
rad = (1.0 * angle / 180) * M_PI; //(角度转换为弧度)M_PI是圆周率
#if 0 //非水平方向
matrix.xx = (FT_Fixed)( cos(rad) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(rad) * 0x10000L);
matrix.yx = (FT_Fixed)( sin(rad) * 0x10000L);
matrix.yy = (FT_Fixed)( cos(rad) * 0x10000L);
#endif
#if 1 //斜体 水平方向显示的
matrix.xx = (FT_Fixed)( cos(rad) * 0x10000L);// 水平方向的缩放和旋转
//变换矩阵的水平缩放和旋转分量。cos(rad) * 0x10000L 将弧度 rad 的余弦值放大 65536 倍(0x10000L 是 2^16),以便于定点数表示
matrix.xy = (FT_Fixed)( sin(rad) * 0x10000L);// 水平和垂直方向的旋转
matrix.yx = (FT_Fixed)( 0 * 0x10000L); // 垂直方向的倾斜(这里为0,表示没有倾斜)
matrix.yy = (FT_Fixed)( 1 * 0x10000L); // 垂直方向的缩放
#endif
/* 设置 */
FT_Set_Transform(face, &matrix, &pen);
//FT_Set_Transform:FreeType库中的一个函数,用于设置变换矩阵和原点
//face:已经加载的字体面对象
//&matrix:指向变换矩阵的指针。这个矩阵用于在渲染字符之前对其进行变换(例如旋转、缩放、斜切等)
//&pen:指向原点位置的指针。这个原点位置用于设置文本的起始位置
FT_Set_Pixel_Sizes(face, 50, 0); //设置字体大小
return 0;
}
static void lcd_draw_character(int x, int y,
const wchar_t *str, unsigned int color)
{
unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
FT_GlyphSlot slot = face->glyph;//将当前字体面对象的字形槽指针赋值给变量 slot
size_t len = wcslen(str); //计算字符的个数 wcslen 函数计算宽字符字符串的长度,即字符的个数,不包括终止的空字符(L'\0')
long int temp;
int n;
int i, j, p, q;
int max_x, max_y, start_y, start_x;
// 循环加载各个字符
for (n = 0; n < len; n++) {
// 加载字形、转换得到位图数据
//加载并准备渲染一个字符。它会将字符的字形数据加载到字形槽(glyph slot)中
//FT_LOAD_RENDER: 这是一个标志,指定要渲染字符图像。它意味着不仅要加载字形数据,还要生成一个位图或矢量图形来表示这个字符
//如果函数调用失败(即返回非零值)
if (FT_Load_Char(face, str[n], FT_LOAD_RENDER))
continue;
start_y = y - slot->bitmap_top; //计算字形轮廓上边y坐标起点位置 注意是减去bitmap_top(字形位图顶部相对于基线的垂直距离)
if (0 > start_y) {//如果为负数 如何处理??
q = -start_y;//计算q为start_y的绝对值。这表示字形位图顶部在目标图像中的垂直偏移量
temp = 0;
j = 0;
}
else { // 正数又该如何处理??
q = 0;
temp = width * start_y;
j = start_y;
}
max_y = start_y + slot->bitmap.rows;//计算字形轮廓下边y坐标结束位置 slot->bitmap.rows 是字形位图的高度
if (max_y > (int)height)
max_y = height;
for (; j < max_y; j++, q++, temp += width) {
start_x = x + slot->bitmap_left; //起点位置要加上左边空余部分长度
if (0 > start_x) {
p = -start_x;
i = 0;
}
else {
p = 0;
i = start_x;
}
max_x = start_x + slot->bitmap.width;
if (max_x > (int)width)
max_x = width;
for (; i < max_x; i++, p++) {
// 如果数据不为0,则表示需要填充颜色
if (slot->bitmap.buffer[q * slot->bitmap.width + p])
screen_base[temp + i] = rgb565_color;
}
}
//调整到下一个字形的原点
x += slot->advance.x / 64; //26.6固定浮点格式
y -= slot->advance.y / 64;
}
}
int main(int argc, char *argv[])
{
/* LCD初始化 */
if (fb_dev_init())
exit(EXIT_FAILURE);
/* freetype初始化 */
if (freetype_init(argv[1], atoi(argv[2])))
exit(EXIT_FAILURE);
/* 在LCD上显示中文 */
int y = height * 0.25;
lcd_draw_character(50, 100, L"路漫漫其修远兮,吾将上下而求索", 0x000000);
lcd_draw_character(50, y+100, L"莫愁前路无知己,天下谁人不识君", 0x9900FF);
lcd_draw_character(50, 2*y+100, L"君不见黄河之水天上来,奔流到海不复回", 0xFF0099);
lcd_draw_character(50, 3*y+100, L"君不见高堂明镜悲白发,朝如青丝暮成雪", 0x9932CC);
/* 退出程序 */
FT_Done_Face(face);
FT_Done_FreeType(library);
munmap(screen_base, screen_size);
close(fd);
exit(EXIT_SUCCESS);
}
调用fb_dev_init函数初始化LCD设备,如果失败则退出程序
-
定义局部变量fb_var和fb_fix,用于存储可变和固定的屏幕信息
-
打开framebuffer设备/dev/fb0,获取文件描述符fd
- 如果打开失败,打印错误信息并返回-1
-
使用ioctl函数获取framebuffer设备的可变和固定信息
-
计算screen_size、width和height
-
使用mmap函数将framebuffer设备映射到内存
- 如果映射失败,打印错误信息,关闭文件描述符并返回-1
-
使用memset函数将LCD背景刷成黑色
-
返回0表示初始化成功
调用freetype_init函数初始化FreeType库和加载字体文件,如果失败则退出程序
-
定义局部变量error、pen、matrix和rad
-
初始化FreeType库,创建library对象
-
加载字体文件,创建face对象
- 如果加载字体失败,打印错误信息并退出程序
-
设置字符绘制的原点坐标(0, 0)
-
计算旋转角度angle转换为弧度rad
-
初始化变换矩阵matrix,包括水平和垂直方向的缩放和旋转
-
使用FT_Set_Transform函数设置变换矩阵和原点位置
-
使用FT_Set_Pixel_Sizes函数设置字体大小
-
返回0表示初始化成功
计算要绘制字符的起始位置y
调用lcd_draw_character函数多次绘制不同的中文字符串到LCD上
-
将ARGB8888颜色转换为RGB565颜色
-
获取当前字体面对象的字形槽指针slot
-
计算要绘制的字符串的长度
-
循环处理每个字符
-
加载并渲染字符到字形槽
-
计算字符起始位置start_y。根据start_y是否为负数,进行不同的处理
-
计算字符结束位置max_y。如果max_y超过LCD高度,将其限制在LCD高度范围内
-
绘制字符
-
计算每行的起始位置start_x。根据start_x是否为负数,进行不同的处理
-
计算字符的宽度结束位置max_x。如果max_x超过LCD宽度,将其限制在LCD宽度范围内
-
逐像素绘制字符位图到LCD显存,非零像素填充颜色
-
-
更新下一个字符的绘制起点x和y
-
释放资源
-
调用FT_Done_Face函数释放字体面对象
-
调用FT_Done_FreeType函数释放FreeType库对象
-
调用munmap函数解除内存映射
-
关闭文件描述符fd
退出程序,返回成功状态
开发板验证
./testApp SIMSUN.TTC 50
-
SIMSUN.TTC为字库,需要给权限