UVGUI抗锯齿字模符号显示原理

UVGUI抗锯齿字模符号显示原理

@firestaradmin 2020年12月7日14:24:50

一、浅析LVGL Label显示原理

绘制 label 过程:

lv_draw_label -》 lv_draw_letter -》draw_letter_normal

lv_draw_label

函数原型如下:

/**
 * Write a text
 * @param coords coordinates of the label
 * @param mask the label will be drawn only in this area
 * @param dsc pointer to draw descriptor
 * @param txt `\0` terminated text to write
 * @param hint pointer to a `lv_draw_label_hint_t` variable.
 * It is managed by the drawer to speed up the drawing of very long texts (thousands of lines).
 */
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, lv_draw_label_dsc_t * dsc, const char * txt, lv_draw_label_hint_t * hint)
{
    ...
}
  • coords:label 的坐标区域位置
  • mask:label 的遮罩, 表示要在哪个区域显示
  • dsc:绘制主题相关
  • txt:要显示的文字字符串指针
  • hint:方便计算第一个字符位置的结构体信息

此函数主要收集并判断字符串显示的行数、位置等信息,再去循环调用lv_draw_letter 来显示每一个字符。


lv_draw_letter

/**
 * Draw a letter in the Virtual Display Buffer
 * @param pos_p left-top coordinate of the latter
 * @param clip_area the letter will be drawn only on this area  (truncated to VDB area)
 * @param font_p pointer to font
 * @param letter a letter to draw
 * @param color color of letter
 * @param opa opacity of letter (0..255)
 */
LV_ATTRIBUTE_FAST_MEM static void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
  • pos_p:字符左上角坐标
  • clip_area:在此区域的字符部分才会被显示
  • font_p:字体结构体指针
  • letter:要绘制的字符
  • color:字符颜色
  • opa:字符不透明度(或者是灰度?)
  • blend_mode:混合模式

此函数主要获取字符的描述信息结构体(字体样式,字模的宽、高),并获取字符的字型数据,再调用draw_letter_normal 来显示字符。


draw_letter_normal

LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
  • pos_x:字符左上角坐标 x 值
  • pos_y:字符左上角坐标 y 值
  • g:字符描述信息结构体指针
  • clip_area:只在此区域显示字符
  • map_p:字模数据指针
  • color:颜色

此函数是核心函数,根据字符信息,判断抗锯齿,并且将字模数据按照对应的抗锯齿解析,并绘制到显存中。


二、LVGL 字体 数据结构

LVGL 的字体统一通过以下数据结构管理:

lv_font_glyph_dsc_t

字形描述结构体:

/** Describes the properties of a glyph. */
typedef struct {
    uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width. 8 bit integer, 4 bit fractional */
    uint16_t box_w;  /**< Width of the glyph's bounding box*/
    uint16_t box_h;  /**< Height of the glyph's bounding box*/
    int16_t ofs_x;   /**< x offset of the bounding box*/
    int16_t ofs_y;  /**< y offset of the bounding box*/
    uint8_t bpp;   /**< Bit-per-pixel: 1, 2, 4, 8*/
} lv_font_glyph_dsc_t;
  • adv_w : 字形的绝对宽度,下一个字形在这么多间距后绘制。
  • box_w:字模边框宽度
  • box_h:字模边框高度
  • ofs_x:边框x 坐标偏移
  • ofs_y:边框y 坐标偏移
  • bpp:抗锯齿

lv_font_t

字体结构体

/** Describe the properties of a font*/
typedef struct _lv_font_struct {
    /** Get a glyph's  descriptor from a font*/
    bool (*get_glyph_dsc)(const struct _lv_font_struct *, lv_font_glyph_dsc_t *, uint32_t letter, uint32_t letter_next);

    /** Get a glyph's bitmap from a font*/
    const uint8_t * (*get_glyph_bitmap)(const struct _lv_font_struct *, uint32_t);

    /*Pointer to the font in a font pack (must have the same line height)*/
    lv_coord_t line_height;         /**< The real line height where any text fits*/
    lv_coord_t base_line;           /**< Base line measured from the top of the line_height*/
    uint8_t subpx  : 2;             /**< An element of `lv_font_subpx_t`*/
    void * dsc;                     /**< Store implementation specific or run_time data or caching here*/
#if LV_USE_USER_DATA
    lv_font_user_data_t user_data;  /**< Custom user data for font. */
#endif

} lv_font_t;
  • get_glyph_dsc:获取字形描述信息的函数指针
  • get_glyph_bitmap:获取字形数据的函数指针
  • line_height:真实的行高度
  • base_line:基线 从行高度的上方开始测量
  • dsc:储存细节实现或者运行数据或者缓存
  • user_data:自定义数据

take a chestnut☺:


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!