【电子量产工具】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 库,在编译时要进行库链接。

相关文章
|
中间件
【电子量产工具】大纲分析
【电子量产工具】大纲分析
88 0
【电子量产工具】6. 业务系统
【电子量产工具】6. 业务系统
84 0
|
6月前
|
物联网 大数据
墨水屏电子纸标签/电子纸价签领域如何选择无线通信方案?
很多的厂家都知道,电子标签/电子价签的全套解决方案中,无线通信方案是最核心的,选对了这个方案,整个系统就会成功一半。
|
6月前
|
算法 安全 数据可视化
开题报告-基于嵌入式的数字水印叠加系统与实现
开题报告-基于嵌入式的数字水印叠加系统与实现
|
编解码 中间件 Linux
【电子量产工具】1.显示系统
【电子量产工具】1.显示系统
104 0
【电子量产工具】5.页面系统
【电子量产工具】5.页面系统
56 0
|
存储 UED
【电子量产工具】2.输入系统
【电子量产工具】2.输入系统
73 0
|
vr&ar
【电子量产工具】4. UI系统
【电子量产工具】4. UI系统
84 0
|
机器学习/深度学习 存储 传感器
自动驾驶的“天眼”!聊一聊高精地图领域中所有主流的制作方案(下)
在过去几年中,自动驾驶一直是最受欢迎和最具挑战性的话题之一。在实现完全自主的道路上,研究人员利用了各种传感器,如激光雷达、相机、惯性测量单元(IMU)和GPS,并开发了用于自动驾驶应用的智能算法,如目标检测、目标分割、障碍避免和路径规划。近年来,高清晰度(HD)地图引起了广泛关注。
自动驾驶的“天眼”!聊一聊高精地图领域中所有主流的制作方案(下)
|
传感器 存储 数据采集
自动驾驶的“天眼”!聊一聊高精地图领域中所有主流的制作方案(上)
在过去几年中,自动驾驶一直是最受欢迎和最具挑战性的话题之一。在实现完全自主的道路上,研究人员利用了各种传感器,如激光雷达、相机、惯性测量单元(IMU)和GPS,并开发了用于自动驾驶应用的智能算法,如目标检测、目标分割、障碍避免和路径规划。近年来,高清晰度(HD)地图引起了广泛关注。
自动驾驶的“天眼”!聊一聊高精地图领域中所有主流的制作方案(上)