目录
前言
一、文字数据结构抽象
1.描述一个文字的位图
2.描述一个字库操作
3.font_manager.h
二、实现Freetype封装
1.freetype.c
三、实现文字管理
1.font_manager.c
四、单元测试
1.font_test.c
2.disp_manager.c
3.disp_manager.h
4.上机测试
前言
前面我们实现了显示系统框架和输入系统框架,链接:
- 量产工具一一显示系统(一)-CSDN博客
- 量产工具一一输入系统(二)-CSDN博客
接下来我们来实现文字系统框架。
一、文字数据结构抽象
描述字符的方式:
- 1.位置、大小
- 2.点阵
点阵可以从固定大小的点阵字体文件中获得,也可以从Freetype的矢量字体文件中获得,所以我们需要抽象出一个结构体用来描述这些字符,一个结构体描述一个文字的位图,一个结构体描述一个字库操作。
1.描述一个文字的位图
2.描述一个字库操作
使用点阵绘制文字时:每个文字的大小一样,前后文件互不影响,使用Freetype绘制文字时:大小可能不同,前面文字会影响后面文字,例如:
对于单个Freetype字符,格式如下:
所以我们要抽象出一个结构体FontBitMap,能描述一个“字符”:位置、大小、位图,我们还要抽象出一个结构体FontOpr,能描述字体的操作,比如Freetype的操作、固定点阵字体的操作。
3.font_manager.h
#ifndef _FONT_MANAGER_H
#define _FONT_MANAGER_H#include <common.h>typedef struct FontBitMap {Region tRegion;int iCurOriginX;int iCurOriginY;int iNextOriginX;int iNextOriginY;unsigned char *pucBuffer;
}FontBitMap,*PFontBitMap;typedef struct FontOpr {char *name;int (*FontInit)(char *aFineName);int (*SetFontSize)(int iFontSize);int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);int (*GetStringRegionCar)(char *str, PRegionCartesian ptRegionCar);struct FontOpr *ptNext;
}FontOpr,*PFontOpr;void RegisterFont(PFontOpr ptFontOpr);void FontSystemRegister(void);int SelectAndInitFont(char *aFontOprName, char *aFontFileName);
int SetFontSize(int iFontSize);
int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap);#endif
二、实现Freetype封装
首先我们需要安装和交叉编译工具链 freetype,编译时链接到 freetype 库,Freetype详细介绍可看:
- 交叉编译freetype-CSDN博客
- Freetype 介绍和使用_freetype库简介和使用方式-CSDN博客
位图推导:
1.freetype.c
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <sys/ioctl.h>
#include <font_manager.h>#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_Hstatic FT_Face g_tFace;
static int g_iDefaultFontSize = 12;static int FreeTypeFontInit(char *aFineName)
{FT_Library library;int error;error = FT_Init_FreeType( &library ); /* initialize library */ if (error){printf("FT_Init_FreeType err\n");return -1;}error = FT_New_Face(library, aFineName, 0, &g_tFace ); /* create face object */if (error){printf("FT_New_Face err\n");return -1;}FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);return 0;
}static int FreeTypeSetFontSize(int iFontSize)
{FT_Set_Pixel_Sizes(g_tFace, iFontSize, 0);return 0;
}static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{int error;FT_Vector pen;FT_GlyphSlot slot = g_tFace->glyph;pen.x = ptFontBitMap->iCurOriginX * 64; /* 单位: 1/64像素 */pen.y = ptFontBitMap->iCurOriginY * 64; /* 单位: 1/64像素 *//* 转换:transformation */FT_Set_Transform(g_tFace, 0, &pen);/* 加载位图: load glyph image into the slot (erase previous one) */error = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}ptFontBitMap->pucBuffer = slot->bitmap.buffer;ptFontBitMap->tRegion.iLeftUpX = slot->bitmap_left;ptFontBitMap->tRegion.iLeftUpY = ptFontBitMap->iCurOriginY*2 - slot->bitmap_top;ptFontBitMap->tRegion.iWidth = slot->bitmap.width;ptFontBitMap->tRegion.iHeigh = slot->bitmap.rows;ptFontBitMap->iNextOriginX = ptFontBitMap->iCurOriginX + slot->advance.x / 64;ptFontBitMap->iNextOriginY = ptFontBitMap->iCurOriginY;return 0;
}static struct FontOpr g_tFreetypeOpr = {.name = "freetype",.FontInit = FreeTypeFontInit,.SetFontSize = FreeTypeSetFontSize,.GetFontBitMap = FreeTypeGetFontBitMap,
};void FreetypeRegister(void)
{RegisterFont(&g_tFreetypeOpr);}
三、实现文字管理
我们可能要用到的字体有多种,那么怎么选择用哪个字符呢,所以我们要编写一个程序管理多种字符。
1.font_manager.c
#include <font_manager.h>
#include <string.h>static PFontOpr g_ptFonts = NULL;
static PFontOpr g_ptDefaulFontOpr = NULL;void RegisterFont(PFontOpr ptFontOpr)
{ptFontOpr->ptNext = g_ptFonts;g_ptFonts = ptFontOpr;
}void FontSystemRegister(void)
{extern void FreetypeRegister(void);FreetypeRegister();
}int SelectAndInitFont(char *aFontOprName, char *aFontFileName)
{PFontOpr ptTmp = g_ptFonts;while (ptTmp){if (strcmp(ptTmp->name, aFontOprName) == 0)break;ptTmp = ptTmp->ptNext;}if (!ptTmp)return -1;g_ptDefaulFontOpr = ptTmp;return ptTmp->FontInit(aFontFileName);
}int SetFontSize(int iFontSize)
{return g_ptDefaulFontOpr->SetFontSize(iFontSize);
}int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{return g_ptDefaulFontOpr->GetFontBitMap(dwCode, ptFontBitMap);
}
四、单元测试
在之前写过的 disp_manager.c 文件代码添加一个绘制函数。
1.font_test.c
2.disp_manager.c
新添加void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)函数。
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)
{int i, j, p, q;int x = ptFontBitMap->tRegion.iLeftUpX;int y = ptFontBitMap->tRegion.iLeftUpY;int x_max = x + ptFontBitMap->tRegion.iWidth;int y_max = y + ptFontBitMap->tRegion.iHeigh;int width = ptFontBitMap->tRegion.iWidth;unsigned char *buffer = ptFontBitMap->pucBuffer;//printf("x = %d, y = %d\n", x, y);for ( j = y, q = 0; j < y_max; j++, q++ ){for ( i = x, p = 0; i < x_max; i++, p++ ){if ( i < 0 || j < 0 ||i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres )continue;//image[j][i] |= bitmap->buffer[q * bitmap->width + p];if (buffer[q * width + p])PutPixel(i, j, dwColor);}}}
3.disp_manager.h
新添加声明函数void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);
新增头文件 #include <font_manager.h>
#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H#include <common.h>
#include <font_manager.h>typedef struct DispBuff {int iXres;int iYres;int iBpp;char *buff;
}DispBuff, *PDispBuff;typedef struct DispOpr {char *name;int (*DeviceInit)(void);int (*DeviceExit)(void);int (*GetBuffer)(PDispBuff ptPDispBuff);int (*FlushRegion)(PRegion ptRegion, PDispBuff ptPDispBuff);struct DispOpr *ptNext;
}DispOpr, *PDispOpr;int PutPixel(int x, int y, unsigned int dwColor);
void RegisterDisplay(PDispOpr ptPDispOpr);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
PDispBuff GetDisplayBuffer(void);
int FlushDisplayRegion(PRegion ptPRegion, PDispBuff ptPDispBuff);
void DisplaySystemRegister(void);
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);#endif
4.上机测试
上电开发板,挂载 Ubuntu 的 NFS 目录,编译测试: