LVGL字体文件格式的文本表示和解析

本文详细介绍了LittlevGL图形库中处理字体文件的函数,包括从字体文件中提取字形位图、字形描述符,以及字形的压缩和解压缩。文中对多个关键函数进行了深入的分析,包括函数逻辑、使用场景和注意事项,展示了如何在实际应用场景中使用这些函数来渲染和管理字体数据。

如何从字体文件中获取字形位图、字形描述符,以及如何进行字形的压缩和解压缩。带着问题,我将逐一解释这些函数,并在最后提供一个简单的示例来展示如何在一个demo中使用这些函数。

函数解释

  1. lv_font_get_bitmap_fmt_txt

lv_font_get_bitmap_fmt_txt 函数是 LittlevGL 图形库中用于从字体文件中提取字形位图数据的函数。这个函数处理了字体数据的不同格式,包括未压缩的位图和使用RLE(Run-Length Encoding)压缩的位图。下面我将详细分析这个函数:

函数原型

const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf)

参数

  1. g_dsc:指向 lv_font_glyph_dsc_t 结构体的指针,包含了字形的元数据,如字形的宽度、高度、x偏移量、y偏移量以及字形的ID。

  2. draw_buf:指向 lv_draw_buf_t 结构体的指针,这是一个绘图缓冲区,用于存储提取出来的字形位图数据。

返回值

函数返回一个 const void * 类型的指针,指向 draw_buf,其中包含了字形的位图数据。

函数逻辑

  1. 获取字体和字形描述信息: 函数从 g_dsc 获取字体指针 font 和字形ID gid

  2. 检查字形ID: 如果 gid 为0,表示没有字形数据,函数返回 NULL

  3. 获取字形位图大小: 计算字形位图的大小 gsize,如果 gsize 为0,表示没有字形数据,函数返回 NULL

  4. 处理未压缩的位图: 如果字体的位图格式是 LV_FONT_FMT_TXT_PLAIN,函数将根据不同的位深(bpp),将字形位图数据从输入缓冲区 bitmap_in 复制到输出缓冲区 bitmap_out

  5. 处理压缩的位图: 如果字体的位图格式不是 LV_FONT_FMT_TXT_PLAIN,函数将调用 decompress 函数对字形位图进行解压缩,并将结果存储在 draw_buf 中。

  6. 返回位图数据: 最终,函数返回 draw_buf 的指针,它现在包含了字形的位图数据。

使用场景

这个函数通常在需要将字符渲染到屏幕上时被调用。例如,在文本显示、编辑或者排版过程中,当需要显示一个字符时,程序会先通过 lv_font_get_glyph_dsc_fmt_txt 获取该字符的字形描述符,然后使用 lv_font_get_bitmap_fmt_txt 获取字形的位图数据,并最终将这些数据绘制到屏幕上。

注意事项

  • 字体文件必须事先加载并正确初始化,以便 lv_font_get_bitmap_fmt_txt 可以正确地访问字形数据。
  • 如果字体数据是压缩的,需要确保 LittlevGL 配置中启用了 LV_USE_FONT_COMPRESSED,并且 decompress 函数被正确实现。
  • 返回的位图数据可能会占用大量内存,尤其是在高分辨率或复杂字形的情况下,因此应当谨慎管理这些资源。

以下是 lv_font_get_bitmap_fmt_txt 函数的详细分析和代码注释:

/**
 * 获取字体中特定字形的位图数据。
 * @param g_dsc 指向字形描述符的指针,包含了字形的元数据。
 * @param draw_buf 指向绘制缓冲区的指针,用于存储位图数据。
 * @return 返回绘制缓冲区的指针,其中包含了字形的位图数据。
 */
const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf)
{
    // 获取字形描述符中已经解析的字体指针
    const lv_font_t * font = g_dsc->resolved_font;

    // 获取指向绘制缓冲区数据的指针
    uint8_t * bitmap_out = draw_buf->data;

    // 获取字体数据块的指针
    lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc;

    // 获取字形ID
    uint32_t gid = g_dsc->gid.index;
    // 如果gid为0,则表示没有字形数据,返回NULL
    if(!gid) return NULL;

    // 获取指向字形描述符的指针
    const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];

    // 计算字形位图的大小
    int32_t gsize = (int32_t) gdsc->box_w * gdsc->box_h;
    // 如果大小为0,则表示没有字形数据,返回NULL
    if(gsize == 0) return NULL;

    // 根据位图格式处理字形数据
    if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) {
        // 处理未压缩的位图格式
        const uint8_t * bitmap_in = &fdsc->glyph_bitmap[gdsc->bitmap_index];
        uint8_t * bitmap_out_tmp = bitmap_out;
        int32_t i = 0;
        int32_t x, y;
        uint32_t stride = lv_draw_buf_width_to_stride(gdsc->box_w, LV_COLOR_FORMAT_A8);

        // 根据每像素的位数(bpp)处理位图数据
        if(fdsc->bpp == 1) {
            // 1bpp位图处理
            for(y = 0; y < gdsc->box_h; y ++) {
                for(x = 0; x < gdsc->box_w; x++, i++) {
                    i = i & 0x7;
                    // 根据当前位的位置,从输入位图中提取相应的位,并转换为掩码
                    uint8_t mask = 0x80 >> i;
                    bitmap_out_tmp[x] = (*bitmap_in & mask) ? 0xff : 0x00;
                    if(i == 7) {
                        bitmap_in++;
                        i = 0;
                    }
                }
                bitmap_out_tmp += stride;
            }
        }
        else if(fdsc->bpp == 2) {
            // 2bpp位图处理
            // ...
            // (省略了2bpp和4bpp的代码,逻辑与1bpp类似,只是掩码和位移不同)
        }
        else if(fdsc->bpp == 4) {
            // 4bpp位图处理
            // ...
        }

        // 返回包含未压缩位图数据的绘制缓冲区
        return draw_buf;
    }
    else {
        // Handle compressed bitmap
#if LV_USE_FONT_COMPRESSED
        // 如果位图是压缩的,进行解压缩处理
        bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED;
        decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], bitmap_out, gdsc->box_w, gdsc->box_h,
                   (uint8_t)fdsc->bpp, prefilter);
        return draw_buf;
#else /*!LV_USE_FONT_COMPRESSED*/
        // 如果没有启用压缩字体支持,输出警告并返回NULL
        LV_LOG_WARN("Compressed fonts is used but LV_USE_FONT_COMPRESSED is not enabled in lv_conf.h");
        return NULL;
#endif
    }

    // 如果没有返回,说明字形在字体中未找到
    return NULL;
}

这个函数首先检查字形ID是否有效,然后根据字形的位图格式(压缩或未压缩)来处理数据。对于未压缩的位图,它会根据每像素的位数(bpp)来逐位解析位图数据,并将其转换为绘制缓冲区可以识别的格式。如果位图是压缩的,它会调用 decompress 函数来进行解压缩。

请注意,由于这是一个大型函数,我省略了2bpp和4bpp位图处理的具体代码,以及压缩位图解压缩的实现细节。在实际应用中,你需要确保 LV_USE_FONT_COMPRESSED 宏已定义,并且 decompress 函数被正确实现,以支持压缩位图的解压缩。

lv_font_get_glyph_dsc_fmt_txt

lv_font_get_glyph_dsc_fmt_txt 函数是 LittlevGL 图形库中用于检索特定字符的字形描述符(glyph descriptor)的函数。这个函数是字体系统中的重要组成部分,它允许程序确定如何渲染文本以及文本的视觉属性。以下是对 lv_font_get_glyph_dsc_fmt_txt 函数的详细分析:

函数原型

bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)

参数

  1. font:指向 lv_font_t 结构体的指针,表示要查询的字体。

  2. dsc_out:指向 lv_font_glyph_dsc_t 结构体的指针,用于存储查询到的字形描述符。

  3. unicode_letter:要获取描述符的字符的Unicode编码。

  4. unicode_letter_next:紧随 unicode_letter 之后的字符的Unicode编码,用于考虑字距(kerning)效果。

返回值

函数返回一个布尔值,如果找到了对应的字形描述符,则返回 true;否则返回 false

函数逻辑

  1. 处理制表符:函数首先检查 unicode_letter 是否是制表符('\t'),如果是,则将其替换为空白符(' ')以简化处理。

  2. 获取字形描述符ID:使用 get_glyph_dsc_id 函数获取字符 unicode_letter 对应的字形描述符ID。

  3. 检查字形ID:如果得到的字形ID为0,表示没有找到对应的字形,函数返回 false

  4. 获取字距值:如果字体支持字距,函数将计算当前字符和其后一个字符之间的字距值。

  5. 构建字形描述符:使用获取到的字形ID和字距值,函数填充 dsc_out 结构体,包括字形的宽度(box_w)、高度(box_h)、x偏移量(ofs_x)、y偏移量(ofs_y)和推荐前进距离(adv_w)。

  6. 处理制表符宽度:如果原始字符是制表符,函数将字形宽度加倍。

  7. 返回结果:最终,函数返回 true 表示成功找到字形描述符。

使用场景

这个函数通常在需要确定字符的视觉属性时被调用,比如在文本渲染、文本布局或文本宽度计算时。

注意事项

  • 字形描述符包含了渲染字符所需的所有必要信息,包括大小、偏移量和字距调整。
  • 字距值是通过 get_kern_value 函数获取的,它可能依赖于字形的ID或字形的类别。
  • 如果 unicode_letter 是制表符,函数会将其视为一个特殊的空白符,以简化制表符宽度的处理。

通过上述分析,我们可以看到 lv_f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值