【电子量产工具】3.文字系统

简介: 【电子量产工具】3.文字系统

前言

最近看了 电子量产工具 这个项目,本专栏是对该项目的一个总结。


一、文字系统分析

文字管理器下面有 两种 字体表示方式: 点阵字符freetype 字符,具有不同的特点和用途。

使用点阵字库显示英文字母、汉字时,大小固定,如果放大缩小则会模糊可能有锯齿出现,为了解决这个问题,引用矢量字体。

FreeType 字符使用矢量图形描述字体的轮廓和形状,可以按需缩放和变换以适应不同的显示分辨率和大小。FreeType 字符具有良好的平滑度和可扩展性,可以提供更高品质的字符显示效果。


这里主要 介绍使用 FreeType 来显示字符, 在写程序前 要先了解 FreeType 的一些基础知识。


二、使用freetype得到位图

① 初始化freetype库.

error = FT_Init_FreeType( &library );

② 加载字体文件,保存在&face 中。

FT_GlyphSlot slot;
error = FT_New_Face( library, argv[1], 0, &face );
slot = face->glyph;

③ 设置字体大小.

FT_Set_Pixel_Sizes(face, font_size, 0);

④ 根据编码值得到位图.

error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );

三、结构体字体系统模块化

  1. 结构体模块化字体显示方式。
typedef struct FontOpr {
  char *name;
  int (*FontInit)(char *aFineName);                 //字符设备初始化
  int (*SetFontSize)(int iFontSize);                    //设置字符大小
  int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);  //获取位图
  struct FontOpr *ptNext;
}FontOpr, *PFontOpr;
  1. 结构体模块化位图。(包括基点坐标,下一个基点坐标等)

四、底层 freetype

  1. 实现 FontOpr 结构体。
static FontOpr g_tFreetypeOpr = {
  .name          = "freetype",
  .FontInit      = FreeTypeFontInit,
  .SetFontSize   = FreeTypeSetFontSize,
  .GetFontBitMap = FreeTypeGetFontBitMap,   
};
  1. 初始化 freetype 字体显示。
static int FreeTypeFontInit(char *aFineName)        // aFineName 是字库名
{
    FT_Library    library;
    int error;
  error = FT_Init_FreeType( &library );             // 初始化               
  if (error)
  {
    printf("FT_Init_FreeType err\n");
    return -1;
  }
    error = FT_New_Face(library, aFineName, 0, &g_tFace );     // 加载(打开)字体
  if (error)
  {
    printf("FT_New_Face err\n");
    return -1;
  }
  FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);   // 设置字体大小
  return 0;
}
  1. 设置字体大小就很简单了。
  2. 获取位图。
/* 根据 dwCode 编码值,获取位图 ptFontBitMap */
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像素 */
  /* 如果不涉及旋转,不涉及多个文字一起显示,就不用调用FT_Set_Transform */
  FT_Set_Transform(g_tFace, 0, &pen); 
  /* 加载位图,根据编码值获取位图,保存在 g_tFace 中 */
  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;
}

五、字体管理层

  1. 将设备注册入 链表。

  2. 根据 name 找到目标设备。
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);      // 根据字库 初始化 framebuffer
}
  1. 向上层提供字体大小 , 获取位图。
    dwCode 是编码值,将位图保存在 函数参数 ptFontBitMap 中。
  2. 要在 屏幕上显示出这些位图, 还需要写 绘制位图 函数。
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;
    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;               // 跳出本次循环
            if (buffer[q * width + p])
              PutPixel(i, j, dwColor);      // 描点函数
        }
    }
}

六、测试程序

  1. 在 main.c 函数中 ,因为字体 在 LCD 上显示,我们要 初始化显示系统并将其 注册入链表,找到需要的显示设备。
  2. 通过字符编码值,找到位图,绘制位图,再改变坐标值。

测试效果:

要显示 中文时,不要忘记使用 wchar_t

注意 : 如果想在代码中能直接使用 UNICODE 值,需要使用 wchar_t,宽字符。

#include <wchar.h>
wchar_t *str= L"你好hi";


总结

找 位图以及位图的坐标 是一个难点,要好好体会。

使用 freetype 库,在编译时要进行库链接。

相关文章
|
计算机视觉
YOLOv5改进 | 检测头篇 | 增加辅助检测头利用AFPN改进Head(附详细修改教程)
YOLOv5改进 | 检测头篇 | 增加辅助检测头利用AFPN改进Head(附详细修改教程)
879 0
|
算法 数据可视化 安全
Docker-11:Docekr安装Etcd
Docker方式安装etcd
1632 0
Docker-11:Docekr安装Etcd
|
11月前
|
机器学习/深度学习 自然语言处理
掩码语言模型(MLM)
【10月更文挑战第6天】掩码语言模型(MLM)
|
存储 Linux 调度
OpenStack如何支持虚拟化技术?
【8月更文挑战第21天】
652 0
|
Java Maven 开发工具
解决依赖冲突中NoSuchMethodError错误的方法探索
解决 `NoSuchMethodError`错误是一个需要精细操作的过程,它要求开发者不仅要有扎实的编程基础,还需要对项目依赖关系有深刻的理解。通过以上探讨的策略,希望能帮助你有效地解决这一问题。
384 14
|
网络安全 数据安全/隐私保护
华为交换机基本配置之Telnet和SSH方式远程登录
华为交换机基本配置之Telnet和SSH方式远程登录
2544 0
|
人工智能 并行计算 芯片
在大模型AI的下一个战场,为中小创新企业重构竞争格局
在大模型AI的下一个战场,为中小创新企业重构竞争格局
|
存储 缓存 前端开发
【硬件知识】了解服务器基础硬件组成
【硬件知识】了解服务器基础硬件组成
1016 1
|
机器学习/深度学习 算法 数据可视化
LightCLIP来啦 | 其实可以使用多级交互范式来训练轻量级CLIP模型
LightCLIP来啦 | 其实可以使用多级交互范式来训练轻量级CLIP模型
795 2
|
Java Apache
Java代码使用POI导出的单元格加上边框和背景色
【5月更文挑战第3天】Java代码使用POI导出的单元格加上边框和背景色
1226 0