mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(freetype): support bold and italic (#2824)
* feat(freetype):support bold and italic * fix(format): replace code-format.sh with code-format.py Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
6791522588
commit
81f7d50c45
2
.github/workflows/check_style.yml
vendored
2
.github/workflows/check_style.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
sudo apt-get update -y -qq
|
||||
sudo apt-get install astyle
|
||||
- name: Format code
|
||||
run: ./code-format.sh
|
||||
run: python code-format.py
|
||||
working-directory: scripts
|
||||
- name: Check that repository is clean
|
||||
run: git diff --exit-code || (echo "Please apply the preceding diff to your code or run scripts/code-format.sh"; false)
|
||||
|
@ -1,6 +1,6 @@
|
||||
```eval_rst
|
||||
.. include:: /header.rst
|
||||
:github_url: |github_link_base|/libs/bmp.md
|
||||
:github_url: |github_link_base|/libs/freetype.md
|
||||
```
|
||||
|
||||
# FreeType support
|
||||
@ -19,11 +19,33 @@ Interface to [FreeType](https://www.freetype.org/) to generate font bitmaps run
|
||||
|
||||
Enable `LV_USE_FREETYPE` in `lv_conf.h`.
|
||||
|
||||
See the examples below.
|
||||
To cache the glyphs from the opened fonts set `LV_FREETYPE_CACHE_SIZE >= 0` and then use the following macros for detailed configuration:
|
||||
1. `LV_FREETYPE_CACHE_SIZE`:maximum memory(bytes) used to cache font bitmap, outline, character maps, etc. 0 means use the system default value, less than 0 means disable cache.Note: that this value does not account for managed FT_Face and FT_Size objects.
|
||||
1. `LV_FREETYPE_CACHE_FT_FACES`:maximum number of opened FT_Face objects managed by this cache instance.0 means use the system default value.Only useful when LV_FREETYPE_CACHE_SIZE >= 0.
|
||||
1. `LV_FREETYPE_CACHE_FT_SIZES`:maximum number of opened FT_Size objects managed by this cache instance. 0 means use the system default value.Only useful when LV_FREETYPE_CACHE_SIZE >= 0.
|
||||
|
||||
When you are sure that all the used fonts size will not be greater than 256, you can enable `LV_FREETYPE_SBIT_CACHE`, which is much more memory efficient for small bitmaps.
|
||||
|
||||
You can use `lv_ft_font_init()` to create FreeType fonts. It returns `true` to indicate success, at the same time, the `font` member of `lv_ft_info_t` will be filled with a pointer to an lvgl font, and you can use it like any lvgl font.
|
||||
|
||||
Font style supports bold and italic, you can use the following macro to set:
|
||||
1. `FT_FONT_STYLE_NORMAL`:default style.
|
||||
1. `FT_FONT_STYLE_ITALIC`:Italic style
|
||||
1. `FT_FONT_STYLE_BOLD`:bold style
|
||||
|
||||
They can be combined.eg:`FT_FONT_STYLE_BOLD | FT_FONT_STYLE_ITALIC`.
|
||||
|
||||
Note that, the FreeType extension doesn't use LVGL's file system.
|
||||
You can simply pass the path to the font as usual on your operating system or platform.
|
||||
|
||||
## Example
|
||||
```eval_rst
|
||||
|
||||
.. include:: ../../examples/libs/freetype/index.rst
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Learn more
|
||||
- FreeType [tutorial](https://www.freetype.org/freetype2/docs/tutorial/step1.html)
|
||||
- LVGL's [font interface](https://docs.lvgl.io/v7/en/html/overview/font.html#add-a-new-font-engine)
|
||||
|
@ -12,7 +12,10 @@ void lv_example_freetype_1(void)
|
||||
info.name = "./lvgl/examples/libs/freetype/arial.ttf";
|
||||
info.weight = 24;
|
||||
info.style = FT_FONT_STYLE_NORMAL;
|
||||
lv_ft_font_init(&info);
|
||||
info.mem = NULL;
|
||||
if(!lv_ft_font_init(&info)) {
|
||||
LV_LOG_ERROR("create failed.");
|
||||
}
|
||||
|
||||
/*Create style with the new font*/
|
||||
static lv_style_t style;
|
||||
|
@ -576,6 +576,16 @@
|
||||
#if LV_USE_FREETYPE
|
||||
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
|
||||
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
|
||||
/* if font size >= 256, must be configured as image cache */
|
||||
#define LV_FREETYPE_SBIT_CACHE 0
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 0
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
|
5
scripts/code-format.py
Executable file
5
scripts/code-format.py
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
|
||||
os.system('astyle --options=code-format.cfg "../src/*.c,*.h"')
|
@ -1 +0,0 @@
|
||||
astyle --options=code-format.cfg "../src/*.c,*.h"
|
@ -14,6 +14,8 @@
|
||||
#include FT_GLYPH_H
|
||||
#include FT_CACHE_H
|
||||
#include FT_SIZES_H
|
||||
#include FT_IMAGE_H
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -67,8 +69,16 @@ static FT_Library library;
|
||||
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||
static FTC_Manager cache_manager;
|
||||
static FTC_CMapCache cmap_cache;
|
||||
static FTC_SBitCache sbit_cache;
|
||||
static FTC_SBit sbit;
|
||||
static FT_Face current_face = NULL;
|
||||
|
||||
#if LV_FREETYPE_SBIT_CACHE
|
||||
static FTC_SBitCache sbit_cache;
|
||||
static FTC_SBit sbit;
|
||||
#else
|
||||
static FTC_ImageCache image_cache;
|
||||
static FT_Glyph image_glyph;
|
||||
#endif
|
||||
|
||||
#else
|
||||
static lv_faces_control_t face_control;
|
||||
#endif
|
||||
@ -104,11 +114,19 @@ bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
#if LV_FREETYPE_SBIT_CACHE
|
||||
error = FTC_SBitCache_New(cache_manager, &sbit_cache);
|
||||
if(error) {
|
||||
LV_LOG_ERROR("Failed to open sbit cache");
|
||||
goto Fail;
|
||||
}
|
||||
#else
|
||||
error = FTC_ImageCache_New(cache_manager, &image_cache);
|
||||
if(error) {
|
||||
LV_LOG_ERROR("Failed to open image cache");
|
||||
goto Fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
Fail:
|
||||
@ -176,6 +194,36 @@ static FT_Error font_face_requester(FTC_FaceID face_id,
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
static bool get_bold_glyph(const lv_font_t * font, FT_Face face,
|
||||
FT_UInt glyph_index, lv_font_glyph_dsc_t * dsc_out)
|
||||
{
|
||||
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
|
||||
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||
int strength = 1 << 6;
|
||||
FT_Outline_Embolden(&face->glyph->outline, strength);
|
||||
}
|
||||
}
|
||||
|
||||
if(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6);
|
||||
dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = face->glyph->bitmap_top -
|
||||
face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
|
||||
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
|
||||
{
|
||||
@ -192,20 +240,51 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
|
||||
|
||||
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
|
||||
|
||||
FT_Face face;
|
||||
FTC_ImageTypeRec desc_sbit_type;
|
||||
FTC_FaceID face_id = (FTC_FaceID)dsc->face_id;
|
||||
FTC_Manager_LookupFace(cache_manager, face_id, &face);
|
||||
FT_Size face_size;
|
||||
struct FTC_ScalerRec_ scaler;
|
||||
scaler.face_id = face_id;
|
||||
scaler.width = dsc->height;
|
||||
scaler.height = dsc->height;
|
||||
scaler.pixel = 1;
|
||||
if(FTC_Manager_LookupSize(cache_manager, &scaler, &face_size) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
desc_sbit_type.face_id = face_id;
|
||||
desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||
desc_sbit_type.height = dsc->height;
|
||||
desc_sbit_type.width = dsc->height;
|
||||
FT_Face face = face_size->face;
|
||||
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, face_id, charmap_index, unicode_letter);
|
||||
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL);
|
||||
dsc_out->is_placeholder = glyph_index == 0;
|
||||
|
||||
if(dsc->style & FT_FONT_STYLE_ITALIC) {
|
||||
FT_Matrix italic_matrix;
|
||||
italic_matrix.xx = 1 << 16;
|
||||
italic_matrix.xy = 0x5800;
|
||||
italic_matrix.yx = 0;
|
||||
italic_matrix.yy = 1 << 16;
|
||||
FT_Set_Transform(face, &italic_matrix, NULL);
|
||||
}
|
||||
|
||||
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||
current_face = face;
|
||||
if(!get_bold_glyph(font, face, glyph_index, dsc_out)) {
|
||||
current_face = NULL;
|
||||
return false;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
FTC_ImageTypeRec desc_type;
|
||||
desc_type.face_id = face_id;
|
||||
desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||
desc_type.height = dsc->height;
|
||||
desc_type.width = dsc->height;
|
||||
|
||||
#if LV_FREETYPE_SBIT_CACHE
|
||||
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_type, glyph_index, &sbit, NULL);
|
||||
if(error) {
|
||||
LV_LOG_ERROR("SBitCache_Lookup error");
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_out->adv_w = sbit->xadvance;
|
||||
@ -214,16 +293,53 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
|
||||
dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||
dsc_out->is_placeholder = glyph_index == 0;
|
||||
#else
|
||||
FT_Error error = FTC_ImageCache_Lookup(image_cache, &desc_type, glyph_index, &image_glyph, NULL);
|
||||
if(error) {
|
||||
LV_LOG_ERROR("ImageCache_Lookup error");
|
||||
return false;
|
||||
}
|
||||
if(image_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
LV_LOG_ERROR("Glyph_To_Bitmap error");
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
|
||||
dsc_out->adv_w = (glyph_bitmap->root.advance.x >> 16);
|
||||
dsc_out->box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = glyph_bitmap->left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = glyph_bitmap->top -
|
||||
glyph_bitmap->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||
#endif
|
||||
|
||||
end:
|
||||
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
|
||||
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter)
|
||||
{
|
||||
LV_UNUSED(font);
|
||||
LV_UNUSED(unicode_letter);
|
||||
|
||||
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
|
||||
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||
if(current_face && current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
|
||||
return (const uint8_t *)(current_face->glyph->bitmap.buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_FREETYPE_SBIT_CACHE
|
||||
return (const uint8_t *)sbit->buffer;
|
||||
#else
|
||||
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
|
||||
return (const uint8_t *)glyph_bitmap->bitmap.buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool lv_ft_font_init_cache(lv_ft_info_t * info)
|
||||
@ -297,6 +413,7 @@ void lv_ft_font_destroy_cache(lv_font_t * font)
|
||||
|
||||
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc);
|
||||
if(dsc) {
|
||||
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc->face_id);
|
||||
lv_mem_free(dsc->face_id);
|
||||
lv_mem_free(dsc->font);
|
||||
lv_mem_free(dsc);
|
||||
@ -380,6 +497,22 @@ static bool get_glyph_dsc_cb_nocache(const lv_font_t * font,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||
int strength = 1 << 6;
|
||||
FT_Outline_Embolden(&face->glyph->outline, strength);
|
||||
}
|
||||
|
||||
if(dsc->style & FT_FONT_STYLE_ITALIC) {
|
||||
FT_Matrix italic_matrix;
|
||||
italic_matrix.xx = 1 << 16;
|
||||
italic_matrix.xy = 0x5800;
|
||||
italic_matrix.yx = 0;
|
||||
italic_matrix.yy = 1 << 16;
|
||||
FT_Outline_Transform(&face->glyph->outline, &italic_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if(error) {
|
||||
return false;
|
||||
@ -393,6 +526,10 @@ static bool get_glyph_dsc_cb_nocache(const lv_font_t * font,
|
||||
face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||
|
||||
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
|
||||
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,12 @@ void lv_extra_init(void)
|
||||
#endif
|
||||
|
||||
#if LV_USE_FREETYPE
|
||||
/*Init freetype library
|
||||
*Cache max 64 faces and 1 size*/
|
||||
lv_freetype_init(0, 0, LV_FREETYPE_CACHE_SIZE);
|
||||
/*Init freetype library*/
|
||||
# if LV_FREETYPE_CACHE_SIZE >= 0
|
||||
lv_freetype_init(LV_FREETYPE_CACHE_FT_FACES, LV_FREETYPE_CACHE_FT_SIZES, LV_FREETYPE_CACHE_SIZE);
|
||||
# else
|
||||
lv_freetype_init(0, 0, 0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_FFMPEG
|
||||
|
@ -1867,6 +1867,34 @@
|
||||
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||
#endif
|
||||
#endif
|
||||
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
|
||||
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
|
||||
/* if font size >= 256, must be configured as image cache */
|
||||
#ifndef LV_FREETYPE_SBIT_CACHE
|
||||
#ifdef CONFIG_LV_FREETYPE_SBIT_CACHE
|
||||
#define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE
|
||||
#else
|
||||
#define LV_FREETYPE_SBIT_CACHE 0
|
||||
#endif
|
||||
#endif
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#ifndef LV_FREETYPE_CACHE_FT_FACES
|
||||
#ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES
|
||||
#define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES
|
||||
#else
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_FREETYPE_CACHE_FT_SIZES
|
||||
#ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES
|
||||
#else
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user