图文使用freetype渲染字体+字体颜色+字体大小

2023-10-26

freetype的介绍各种博客都有,可以搜索看看。

freetype2.8的源码及编译出的库及头文件链接:https://download.csdn.net/download/weixin_40550094/12117925

我这边就直接写demo,本demo可以生成带颜色的bitmap;

使用freetype显示一个字符简单,网上示例也很多,但是将整屏的数据都一起传递给freetype,让其生成整屏完整的bitmap,网上几乎没有找到,再加上字体的渲染,就更少之有少,本问应用是24行40列的电视图文显示使用,也会提供本范例编译出来的freetype库文件及头文件的连接。

本范例实现整屏数据整体转换,整体渲染字色,大小和间距需要按需调整,可以NewFTString中调整;

FT_Set_Char_Size设置大小及分辨率;

#include "ftglyph.h"
#include "freetype.h"
#include <sys/stat.h>


static S32 indexLength = 0;
#define WIDTH_TTX   1280
#define HEIGHT_TTX  720
#define MAX_GLYPHS      1024

/* origin is the upper left corner */
#define dataLength (24 * 40)
static U32 dataIndexBuf[dataLength];

unsigned char* imageBuffer;

static FT_Face pFTFace;
static FT_Library library;

typedef struct FTCode_ {
    FT_ULong code;
    char utf8str[8];
}FTCode;

typedef struct FTStrImage {
    unsigned int width;
    unsigned int height;
    unsigned char* imageBuffer;
}FTStrImage;


typedef struct TGlyph_
{
    FT_UInt index;
    FT_Vector pos;
    FT_BBox drawBox;
    FT_Glyph glyph;
} TGlyph, *PGlyph;

typedef struct {
    unsigned char* image;
    unsigned int width;
    unsigned int height;
    unsigned int strLen;
}FTString;


struct color_ttx
{
    U8 blue;
    U8 green;
    U8 red;
};
color_ttx color_BITMAP[6]
{
    {0x00,0x00,0xff},/**red*/
    {0x00,0xFF,0x00},/**green**/
    {0xFF,0x00,0x00},/**blue**/
    {0x00,0x00,0x00},/**black**/
    {0xFF,0xFF,0xFF},/**white**/
    {0x00,0xFF,0xFF}/**yellow**/
};

static FTStrImage strim;

S32 initFontLib()
{
    FT_Error error = FT_Init_FreeType(&library);
    if (error)
    {
        LOGE("error = %d\n", error);
        return 0;
    }
    error = FT_New_Face(library, "/factory/atv/font/文件名.ttf", 0, &pFTFace);
    if (error == FT_Err_Unknown_File_Format )
    {
        LOGE(" ERROR: fonts not support format!\n");
        return 0;
    }
    else if (error)
    {
        LOGE("ERROR: fonts file cannot open!\n");
        return 0;
    }
    return 0;
}

 

S32 deInitFontLib()
{
    //free face?
    FT_Done_Face(pFTFace);
    pFTFace = NULL;
    free(pFTFace);

    //free FreeType Lib
    FT_Done_FreeType(library);
    library = NULL;

    return 0;
}

FTStrImage NewFTString()

{
    FT_Error error;
    FT_Set_Char_Size(pFTFace,16 << 6,16 << 6 ,120,120);
    FT_GlyphSlot slot = pFTFace->glyph;
    FT_UInt glyph_index = 0;
    FT_Bool use_kerning = FT_HAS_KERNING(pFTFace);
    FT_UInt previous = 0;
    FTCode* codes = 0;
    U32 spacing = 10;
    int pen_x = 0;
    int pen_y = 0;
    TGlyph glyphs[MAX_GLYPHS];
    FT_UInt num_glyphs = 0;
    FT_BBox bbox;
    U32 charSpace = 20;
    bbox.xMin = bbox.yMin = 100000;
    bbox.xMax = bbox.yMax = -100000;
    PGlyph glyph = glyphs;

    U32 line = 23;
    LOGE("use_kerning = %d",use_kerning);
    for( unsigned int n = 0; n < indexLength; n++)
    {
        FT_BBox glyph_bbox;
        memset(&glyph_bbox,0x00,sizeof(glyph_bbox));
        if((n%40 == 0) && (n != 0))
        {
            pen_y = spacing + pen_y + 10;
            pen_x = 0;
            line--;
        }

        glyph->index = FT_Get_Char_Index(pFTFace, dataIndexBuf[dataLength    - (24 - line)*40 + n %40]);
        if ( use_kerning && previous && glyph->index)
        {
            FT_Vector delta;
            FT_Get_Kerning(pFTFace, previous, glyph->index,
            FT_KERNING_DEFAULT, &delta );
            pen_x += delta.x >> 6;
            LOGE("pen_x = %d delta.x = %d\n",pen_x,delta.x);
        }
        glyph->pos.x = pen_x;
        glyph->pos.y = pen_y;
        error = FT_Load_Glyph(pFTFace, glyph->index, FT_LOAD_DEFAULT);
        if ( error )
        {
            LOGE("ERROR: FT_Load_Glyph\n");
        }

        error = FT_Get_Glyph(pFTFace->glyph, &glyph->glyph);//装载一个新的字形图像到字形槽,前面装载的将会从字形槽中抹去
        if ( error )
        {
            LOGE("ERROR: FT_Get_Glyph!\n");
        }


        pen_x += slot->advance.x >> 6;
        previous = glyph->index;

        FT_Glyph_Get_CBox(glyph->glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
        //LOGE("pos.x = %d,pos.y = %d,,previous = %d",glyph->pos.x,glyph->pos.y,previous);
        glyph_bbox.xMin += glyph->pos.x;
        glyph_bbox.xMax += glyph->pos.x;
        glyph_bbox.yMin += glyph->pos.y;
        glyph_bbox.yMax += glyph->pos.y;
        if(n == 0)
        {
            spacing = glyph_bbox.yMax;//用于保存字符的行高
        }
        if (glyph_bbox.xMin < bbox.xMin)
        {
            bbox.xMin = glyph_bbox.xMin;
        }
        if (glyph_bbox.yMin < bbox.yMin)
        {
            bbox.yMin = glyph_bbox.yMin;
        }
        if (glyph_bbox.xMax > bbox.xMax)
        {
            bbox.xMax = glyph_bbox.xMax;
        }
        if (glyph_bbox.yMax > bbox.yMax)
        {
            bbox.yMax = glyph_bbox.yMax;
        }

        //LOGE("[%d %d %d %d]\n", glyph_bbox.xMin, glyph_bbox.yMin, glyph_bbox.xMax, glyph_bbox.yMax);
        glyph->drawBox = glyph_bbox;
        glyph++;
    }

    num_glyphs = glyph - glyphs;
    if ( bbox.xMin > bbox.xMax )
    {
        bbox.xMin = 0;
        bbox.yMin = 0;
        bbox.xMax = 0;
        bbox.yMax = 0;
    }
    unsigned int width = bbox.xMax+1;
    unsigned int height = bbox.yMax-bbox.yMin+1;
    unsigned int start_x = 0;
    unsigned int start_y = 0;
    LOGE("width = %d height = %d \n", width, height);
    for ( unsigned int n = 0; n < indexLength; n++)
    {
        PGlyph pplyph = glyphs+n;
        FT_Vector pen = glyph->pos;
        error = FT_Glyph_To_Bitmap(&pplyph->glyph, FT_RENDER_MODE_NORMAL, &pen, 0);
        if ( !error )
        {
            FT_BitmapGlyph bit = (FT_BitmapGlyph)pplyph->glyph;
            start_x = pplyph->drawBox.xMin;
            start_y = height - (pplyph->drawBox.yMin-bbox.yMin+bit->bitmap.rows);
            for (unsigned int y = 0; y < bit->bitmap.rows; y++)
            {
                for (unsigned int x = 0; x < bit->bitmap.width; x++)
                {
                    unsigned int iy = start_y + y;
                    unsigned int ix = start_x + x;
                    unsigned int index = (iy*width + ix)*4;
                    imageBuffer[index] = color_BITMAP[4].blue;
                    imageBuffer[index+1] = color_BITMAP[4].green;
                    imageBuffer[index+2] = color_BITMAP[4].red;
                    imageBuffer[index+3] = bit->bitmap.buffer[y * bit->bitmap.width + x];
                }
            }
            FT_Done_Glyph(pplyph->glyph);
        }
    }
    //free codes
    free(codes);
    strim.width = width;
    strim.height = height;
    strim.imageBuffer = imageBuffer;//release after
    return strim;
}

 

void test()

{

        initFontLib();
        memset(&strim,0x00,sizeof(strim));
        imageBuffer = (unsigned char*)malloc(WIDTH_TTX*HEIGHT_TTX*4);
        memset(imageBuffer,0x00,WIDTH_TTX*HEIGHT_TTX*4);

        for(U32 loop = 0,value = 0;loop < dataLength;loop ++)
        {
              dataIndexBuf[indexLength] = value + 57360;
              indexLength++;
              if(loop%9 == 0 && loop != 0)
              {
                  value = 0;
              }
              else
              {
                  value++;
              }
        }

       memset(imageBuffer,0x00,WIDTH_TTX*HEIGHT_TTX*4);

       strim = NewFTString();

        Draw_Bitmap_Argb8888(0, 0, strim.width, strim.height, strim.imageBuffer);
        GFX_Flip_Window();

        deInitFontLib();
        free(strim.imageBuffer);
        free(imageBuffer);

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图文使用freetype渲染字体+字体颜色+字体大小 的相关文章

  • android viewpager 更改适配器

    我正在开发一个带有 ViewPager 的应用程序 用于横向滚动表 有时我需要更改适配器以加载一组不同的表 我尝试执行以下操作 mViewPager setAdapter new pagerAdapterPushed getSupportF
  • java.lang.NoClassDefFoundError:解析失败:Ljava/time/Instant;

    目前 我无法解决崩溃问题java lang NoClassDefFoundError Failed resolution of Ljava time Instant Android 7 1 1 Nougat 及更低版本会发生此类崩溃 但我的
  • MariaDB 10 CentOS 7 移动数据目录的问题

    CentOS 7 和 MariaDB 10 的全新 最小 安装 我有一个额外安装的镜像卷 我想将其用于数据目录 当 my cnf mysqld 被注释掉时 启动顺序正常并正常完成 我已经复制了数据 sudo cp R p var lib m
  • 访问数据库的用户列表

    我有一个 MySQL 数据库 由我的一群队友访问 有没有命令可以获取当前正在访问或已经访问并注销的用户的日志信息 从 mysql 工具运行以下命令来查看所有当前正在运行的进程 包括睡眠连接 SHOW PROCESSLIST 或者 您可以查询
  • 设置子视图以适合系统窗口

    我正在设置一个简单的视图 其中仅包含一个空的RelativeLayout
  • 使用动画调整大小

    我用过android windowSoftInputMode 调整调整大小 在清单中防止键盘隐藏活动按钮 它可以工作 但是当键盘打开时 我的按钮会向上移动 这有点紧张 我想知道 我可以有任何动画让它顺利过渡吗
  • SugarORM 从多个表查询?

    我正在为我的 Android 应用程序使用 SugarORM 在我的项目中 我有几个表 我想知道是否有一种方法可以将它们连接到另一个具有多个表中的列的类对象中 如果是 那么示例将非常有帮助 SugarORM 提供了一个用于简单查询的查询生成
  • startAfter 在 Firestore android 中不起作用

    我创建了一个类似测验的应用程序 一次提取 10 个问题 如果用户得到 8 分 满分 10 分 那么我会获取接下来的 10 个问题 但开始之后总是给出相同的回应 val questionCollectionRef db collection
  • 单击网格视图时如何将数组列表(位置)发送到另一个活动

    在这种方法中我收到ArrayList OkHttpHandler handler new OkHttpHandler MainActivity this new OkHttpHandler MyInterface Override publ
  • 如何在 Android 中创建 https 连接?

    我在 Stackoverflow 中找到了很多帖子 但无法找到适用的解决方案 如何在 Android 中创建 https 连接 代码是 HttpParams httpParameters new BasicHttpParams ConnMa
  • 如何在 Android 应用程序中保存数据

    我最近编写了一个 Android 应用程序 这只是一个简单的应用程序 可让您通过几个简单的计数间隔来记录篮球比赛的得分 我收到添加保存功能的要求 这样您就可以保存您的分数 然后将其加载回来 目前 当您停止应用程序时 您的数据就会丢失 所以我
  • 如何在 Android 上注册的应用程序中从我的 WebView 中启动 Web 链接?

    在我的 Android 应用程序中 我有一个 WebView 我想every在我的 WebView 中单击链接以启动我的设备上已注册的应用程序 如果有 否则在外部浏览器中打开 例如 如果用户从 WebView 中单击 Facebook 页面
  • Firestore 客户和发票,修订后的要求

    这个问题是此处发布的问题的后续问题 Firestore 客户和发票 如何建模 https stackoverflow com questions 50867267 firestore clients and invoices how to
  • 为什么函数 printk() 不使用逗号来分隔参数?

    一个例子printk call printk KERN INFO Log message n 也许这个问题更多地是关于C的 因为我之前从未见过C中的函数可以不用逗号分隔参数 这是如何运作的 编译器如何处理这些信息 由于日志级别是一个整数 而
  • 为什么Android中的Sleep首先执行,而不是上面的代码?

    为什么首先执行 try 块 我希望颜色先改变 然后它应该休眠 5000 毫秒 我的意思是系统在颜色改变之前休眠 私有 OnClickListener CheckAnswer new OnClickListener public void o
  • System.DllNotFoundException:> gtk\bin\libgobject-2.0-0.dll

    我已经构建了一个 GUIGithub https github com saigkill PublicanCreators blob master src PublicanCreators Program cs 启动构建的解决方案后 我得到
  • 在 API 21 中 EditText 填充不起作用

    在 API 21 中 EditText 填充不起作用 我尝试在空项目中执行此操作 仅使用单个 editText 但它仍然不起作用 以编程方式设置填充是可行的 但在我的工作项目中 我有很多具有不同填充的 EditText 并且以编程方式设置填
  • 在 Android Studio 中调试应用程序时如何“单步执行”或“单步执行”代码?

    我正在尝试遵循这个使用 Android Studio 进行调试 http developer android com tools debugging debugging studio html 如何单步执行或单步跳过代码 在调试器的变量选项
  • 启动后台进程时ADB进程阻塞

    我正在尝试通过 ADB 在 Android 手机后台运行 shell 脚本 为了简单起见 我们让它睡眠 100 adb shell echo nohup sleep 100 gt data local tmp test sh sh data
  • 制作自定义 Android 闹钟以进行提醒

    我正在制作药物提醒应用程序 在该应用程序中 我添加了添加有关医生预约提醒的功能 在我的应用程序中 允许用户设置他 她自己的日期和时间 并且在该日期和时间应该触发警报 请帮助我 我已从此线程中参考 如何在Android中设置闹钟 https

随机推荐

  • 如何保护 Apache 中的特定 URL

    阻止用户访问特定网页有助于防止他们接触敏感信息 如果您将站点托管在 Apache 服务器上 则可以通过锁定特定 URL 来锁定站点 如果您只需要阻止访问单个页面 则可以锁定 URL 而无需锁定整个站点 使用 Apache 有多种方法可以做到
  • Bash 读取命令

    Bash 附带了许多内置命令 您可以在命令行或 shell 脚本中使用这些命令 在本文中 我们将探讨内置read命令 Bash read内置 read是一个 bash 内置命令 它从标准输入 或文件描述符 读取一行并将该行拆分为单词 第一个
  • 如何在 CentOS 8 上安装 Visual Studio Code

    视觉工作室代码是微软开发的开源 跨平台代码编辑器 它具有内置的调试支持 嵌入式Git控制 语法突出显示 代码完成 集成终端 代码重构和片段 本文介绍如何在 CentOS 8 上安装 Visual Studio Code 先决条件 这些说明假
  • 如何在 CentOS 8 上安装和使用 FFmpeg

    FFmpeg 是一个用于处理多媒体文件的免费开源工具集合 它包含一组共享的音频和视频库 例如libavcodec libavformat和libavutil 使用 FFmpeg 您可以在各种视频和音频格式之间进行转换 设置采样率 捕获流音频
  • 如何在 Debian 9 上安装和配置 Redis

    Redis 是一个开源内存键值数据存储 它可以用作数据库 缓存和消息代理 并支持各种数据结构 如字符串 哈希 列表 集合等 Redis 通过 Redis Sentinel 提供高可用性 包括监控 通知 自动故障转移 它还通过 Redis C
  • Python 列表排序

    对数据进行排序是使用 Python 时最常见的任务之一 例如 您可能希望按姓名对团队成员列表进行排序 或按优先级对项目列表进行排序 本文介绍了如何排序Python 中的列表 Python sort and sorted 在 Python 中
  • 如何在 Debian 9 上安装 TensorFlow

    TensorFlow是由 Google 构建的免费开源机器学习平台 许多组织都在使用它 包括 Twitter PayPal 英特尔 联想和空中客车公司 TensorFlow 可以在 Python 虚拟环境中安装在系统范围内 作为Docker
  • ​如何从 Ubuntu 16.04 升级到 18.04

    最新的 Ubuntu LTS 版本 Ubuntu 18 04 Bionic Beaver 于 2018 年 4 月 26 日发布 支持期为 5 年 直至 2023 年 4 月 在本教程中 我们将向您展示如何升级 Ubuntu 16 04 安
  • Netcat (nc) 命令及示例

    网络猫 或nc 是一个命令行实用程序 它使用 TCP 或 UDP 协议跨网络连接读取和写入数据 它是网络和系统管理员武器库中最强大的工具之一 被视为网络工具中的瑞士军刀 Netcat 是跨平台的 可用于 Linux macOS Window
  • 在 Ubuntu 20.04 上使用 Let's Encrypt 保护 Apache

    Let s Encrypt 是由互联网安全研究小组 ISRG 创建的证书颁发机构 它通过完全自动化的流程提供免费的 SSL 证书 旨在消除手动证书创建 验证 安装和续订 Let s Encrypt 颁发的证书自颁发之日起 90 天内有效 并
  • 如何在 CentOS 8 上安装 VirtualBox

    虚拟盒子是一个开源 跨平台的虚拟化平台 它支持多种来宾操作系统 包括 Linux 和 Windows 并允许您同时运行多个虚拟机 在本教程中 我们将解释如何在 CentOS 8 上安装 VirtualBox 在 CentOS 8 上安装 V
  • 在 CentOS 7 上使用 Let's Encrypt 保护 Apache

    Let s Encrypt 是由互联网安全研究小组 ISRG 开发的免费 自动化 开放的证书颁发机构 Let s Encrypt 颁发的证书自颁发之日起 90 天内有效 并且受到当今所有主要浏览器的信任 在本教程中 我们将介绍在运行 Apa
  • 如何在 Ubuntu 18.04 上安装 PostgreSQL

    PostgreSQL 或 Postgres 是一个开源通用对象关系数据库管理系统 PostgreSQL 具有许多高级功能 可让您创建复杂的 Web 应用程序 在本教程中 我们将向您展示如何在 Ubuntu 18 04 上安装 Postgre
  • 电脑开机后卡死,桌面图标点了没反应怎么办

    今天接到客户的电话 说一台台式办公PC出现故障 具体故障现象如下 电脑可以正常开机 开机后点击桌面上的所有图标都没反应 开始菜单可以点开 点开后里面的内容也无法点击打开 右键点击桌面下方启动栏可以点出来选项卡 但是点击选项卡里的内容无法打开
  • 写代码遇到Qt相关问题

    目录 qt clicked 函数 传递数据 QT读取文件个数 QT读txt数据并求出行数和列数 qt读写json 我的json文件 读写函数 换行和不换行的区别就是参数Indented和Compact的区别 把json写到文件中 QT信号槽
  • 低通滤波器算法实现_控制算法之超前-滞后补偿器(Lead_Lag Compensator)

    Lead Lag控制器主要从频域的角度来对被控系统进行校正 改善系统的频域特性 如相角裕度 幅值裕度以及灵敏度等 从而改善系统的稳定性及控制精度 是一种基于频率响应的校正方法 时域的卷积 频域的乘积 这句话很重要 深入理解 一 Lead L
  • flutter 防止widget rebuild(亲测有效2020篇)

    相比这个问题很多开发着都已经遇到了 头疼了很久了吧 我也是 网上搜到各种方法 试了还是不行 下面我举一下场景 跳转场景 页面A gt 页面B gt 页面C gt 页面D 从上面简单都例子 我很悲催的告诉大家不管我从哪个页面跳哪个页面 从B
  • Awk学习笔记

    Awk学习笔记 整理 Jims of 肥肥世家
  • windows下安装openssl的两种方式

    windows下按装openssl 第一种 第二种 因为工作需要第一次接触openssl 中间踩得坑实在是太多了 最后也算放弃了那种安装方式原则了一个比较简单的 第一种 第一种就是网上平常的说的方法 先下载 ActivePerl 5 24
  • 图文使用freetype渲染字体+字体颜色+字体大小

    freetype的介绍各种博客都有 可以搜索看看 freetype2 8的源码及编译出的库及头文件链接 https download csdn net download weixin 40550094 12117925 我这边就直接写dem