feat(draw/sw): add support for vector fonts (#7560)

This commit is contained in:
Erik Tagirov
2025-03-25 12:18:02 +01:00
committed by GitHub
parent 30075b1786
commit 60d976c466
26 changed files with 666 additions and 100 deletions
@@ -1221,6 +1221,48 @@ Set how to align the lines of the text. Note that it doesn't align the Widget it
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
text_outline_stroke_color
~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the color of letter outline stroke.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> `0x000000`</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> Yes</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
text_outline_stroke_width
~~~~~~~~~~~~~~~~~~~~~~~~~
Set the letter outline stroke width in pixels.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> 0</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> Yes</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> Yes</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
text_outline_stroke_opa
~~~~~~~~~~~~~~~~~~~~~~~
Set the opacity of the letter outline stroke. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency.
.. raw:: html
<ul>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Default</strong> `LV_OPA_COVER`</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> Yes</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline-block; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
Miscellaneous
-------------
+17 -1
View File
@@ -30,7 +30,7 @@ There are two ways to use FreeType:
For UNIX
--------
For UNIX systems, the following is recommended to compile and install FreeType libraries.
For UNIX-like systems, the following is recommended to compile and install FreeType libraries.
- Enter the FreeType source code directory
- ``make``
@@ -124,6 +124,22 @@ please refer to the example code below.
- `FreeType tutorial <https://www.freetype.org/freetype2/docs/tutorial/step1.html>`__
- LVGL's :ref:`add_font`
Rendering vector fonts is supported with VGLite or ThorVG,
when using vector fonts with ThorVG, it is possible to set a letter outline of a different color.
This is achieved by setting the style attributes with the
:cpp:func:`lv_style_set_text_outline_width` and :cpp:func:`lv_style_set_text_outline_color` functions
You will have to account for the increased width and height of letter due to the added letter outline,
to avoid letters overlapping space them out using :cpp:func:`lv_style_set_text_letter_space`
To use vector fonts with ThorVG, you will have to enable ``LV_USE_VECTOR_GRAPHICS`` in ``lv_conf.h``
.. note::
This feature is currently experimental, there are clipping issues especially when using large font sizes.
See the :cpp:func:`lv_example_freetype_2_vector_font` function for a usage example
.. _freetype_example:
@@ -27,6 +27,7 @@ extern "C" {
**********************/
void lv_example_freetype_1(void);
void lv_example_freetype_2(void);
void lv_example_freetype_2_vector_font(uint32_t font_size, uint32_t border_width);
/**********************
* MACROS
+43 -3
View File
@@ -5,9 +5,49 @@
#if LV_FREETYPE_USE_LVGL_PORT
#define PATH_PREFIX "A:"
#else
#define PATH_PREFIX "../"
#define PATH_PREFIX "./"
#endif
/*
* Load a vector font
* ThorVG needs to be enabled, LV_USE_VECTOR_GRAPHICS=1
*/
void lv_example_freetype_2_vector_font(uint32_t font_size, uint32_t border_width)
{
lv_font_t * font = lv_freetype_font_create(PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf",
LV_FREETYPE_FONT_RENDER_MODE_OUTLINE,
font_size,
LV_FREETYPE_FONT_STYLE_NORMAL);
if(!font) {
LV_LOG_ERROR("Freetype font create failed.");
return;
}
/*Create style with the new font*/
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, font);
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
lv_style_set_text_color(&style, lv_color_hex(0xFF0000));
lv_style_set_text_opa(&style, LV_OPA_100);
lv_style_set_text_outline_stroke_opa(&style, LV_OPA_100);
lv_style_set_text_outline_stroke_color(&style, lv_color_hex(0x00FF00));
lv_style_set_text_outline_stroke_width(&style, border_width);
/*Avoid overlapping issue when using letter outlines*/
lv_style_set_text_letter_space(&style, border_width);
lv_style_set_text_line_space(&style, border_width);
/*Create a label with the new style*/
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_add_style(label, &style, 0);
lv_label_set_text(label, "Hello world\nI'm a font created with FreeType");
lv_obj_center(label);
}
/**
* Load a font with FreeType
*/
@@ -16,7 +56,7 @@ void lv_example_freetype_2(void)
/*Create a font*/
lv_font_t * font = lv_freetype_font_create(PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf",
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
24,
400,
LV_FREETYPE_FONT_STYLE_NORMAL);
/* this font is created from a downscaled NotoColorEmoji to 34x32px
@@ -24,7 +64,7 @@ void lv_example_freetype_2(void)
* Command: fonttools subset NotoColorEmoji.ttf --text=😀 */
lv_font_t * font_emoji = lv_freetype_font_create(PATH_PREFIX "lvgl/examples/libs/freetype/NotoColorEmoji-32.subset.ttf",
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
24,
200,
LV_FREETYPE_FONT_STYLE_NORMAL);
if(!font || !font_emoji) {
+12
View File
@@ -348,6 +348,18 @@ props = [
'style_type': 'num', 'var_type': 'lv_text_align_t' , 'default':'`LV_TEXT_ALIGN_AUTO`', 'inherited': 1, 'layout': 1, 'ext_draw': 0,
'dsc': "Set how to align the lines of the text. Note that it doesn't align the Widget itself, only the lines inside the Widget. Possible values are `LV_TEXT_ALIGN_LEFT/CENTER/RIGHT/AUTO`. `LV_TEXT_ALIGN_AUTO` detect the text base direction and uses left or right alignment accordingly"},
{'name': 'TEXT_OUTLINE_STROKE_COLOR',
'style_type': 'color', 'var_type': 'lv_color_t', 'default':'`0x000000`', 'inherited': 1, 'layout': 0, 'ext_draw': 0, 'filtered': 1,
'dsc': "Sets the color of letter outline stroke."},
{'name': 'TEXT_OUTLINE_STROKE_WIDTH',
'style_type': 'num', 'var_type': 'int32_t' , 'default':0, 'inherited': 1, 'layout': 1, 'ext_draw': 0,
'dsc': "Set the letter outline stroke width in pixels."},
{'name': 'TEXT_OUTLINE_STROKE_OPA',
'style_type': 'num', 'var_type': 'lv_opa_t', 'default':'`LV_OPA_COVER`', 'inherited': 1, 'layout': 0, 'ext_draw': 0,
'dsc': "Set the opacity of the letter outline stroke. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency."},
{'section': 'Miscellaneous', 'dsc':'Mixed properties for various purposes.' },
{'name': 'RADIUS',
'style_type': 'num', 'var_type': 'int32_t', 'default':0, 'inherited': 0, 'layout': 0, 'ext_draw': 0,
+24
View File
@@ -674,6 +674,30 @@ void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_ALIGN, v, selector);
}
void lv_obj_set_style_text_outline_stroke_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR, v, selector);
}
void lv_obj_set_style_text_outline_stroke_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH, v, selector);
}
void lv_obj_set_style_text_outline_stroke_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OUTLINE_STROKE_OPA, v, selector);
}
void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
+27
View File
@@ -577,6 +577,30 @@ static inline lv_text_align_t lv_obj_get_style_text_align(const lv_obj_t * obj,
return (lv_text_align_t)v.num;
}
static inline lv_color_t lv_obj_get_style_text_outline_stroke_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_text_outline_stroke_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR));
return v.color;
}
static inline int32_t lv_obj_get_style_text_outline_stroke_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH);
return (int32_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_text_outline_stroke_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OUTLINE_STROKE_OPA);
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_radius(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS);
@@ -858,6 +882,9 @@ void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_
void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_outline_stroke_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_outline_stroke_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_outline_stroke_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_radial_offset(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector);
+13
View File
@@ -315,6 +315,11 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds
draw_letter_dsc.color = dsc->color;
draw_letter_dsc.rotation = dsc->rotation;
/* Set letter outline stroke attributes */
draw_letter_dsc.outline_stroke_width = dsc->outline_stroke_width;
draw_letter_dsc.outline_stroke_opa = dsc->outline_stroke_opa;
draw_letter_dsc.outline_stroke_color = dsc->outline_stroke_color;
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.opa = dsc->opa;
@@ -609,6 +614,14 @@ void lv_draw_unit_draw_letter(lv_draw_task_t * t, lv_draw_glyph_dsc_t * dsc, co
}
dsc->format = g.format;
if(g.format == LV_FONT_GLYPH_FORMAT_VECTOR) {
/*Load the outline of the glyph, even if the function says bitmap*/
g.outline_stroke_width = dsc->outline_stroke_width;
dsc->glyph_data = (void *) lv_font_get_glyph_bitmap(&g, draw_buf);
dsc->format = dsc->glyph_data ? g.format : LV_FONT_GLYPH_FORMAT_NONE;
}
}
else {
dsc->format = LV_FONT_GLYPH_FORMAT_NONE;
+12
View File
@@ -100,6 +100,12 @@ typedef struct {
/**Pointer to an externally stored struct where some data can be cached to speed up rendering*/
lv_draw_label_hint_t * hint;
/* Properties of the letter outlines */
lv_opa_t outline_stroke_opa;
lv_color_t outline_stroke_color;
int32_t outline_stroke_width;
} lv_draw_label_dsc_t;
typedef struct {
@@ -119,6 +125,12 @@ typedef struct {
lv_opa_t opa;
lv_text_decor_t decor : 3;
lv_blend_mode_t blend_mode : 3;
/* Properties of the letter outlines */
lv_opa_t outline_stroke_opa;
int32_t outline_stroke_width;
lv_color_t outline_stroke_color;
} lv_draw_letter_dsc_t;
/**
+3
View File
@@ -50,6 +50,9 @@ struct _lv_draw_glyph_dsc_t {
lv_font_glyph_dsc_t * g;
lv_color_t color;
lv_opa_t opa;
lv_color_t outline_stroke_color;
lv_opa_t outline_stroke_opa;
int32_t outline_stroke_width;
int32_t rotation;
lv_point_t pivot; /**< Rotation pivot point associated with total glyph including line_height */
lv_draw_buf_t * _draw_buf; /**< a shared draw buf for get_bitmap, do not use it directly, use glyph_data instead */
+6 -1
View File
@@ -96,7 +96,12 @@ void lv_draw_sw_init(void)
#endif
#if LV_USE_VECTOR_GRAPHIC && LV_USE_THORVG
tvg_engine_init(TVG_ENGINE_SW, 0);
if(LV_DRAW_SW_DRAW_UNIT_CNT > 1) {
tvg_engine_init(TVG_ENGINE_SW, LV_DRAW_SW_DRAW_UNIT_CNT);
}
else {
tvg_engine_init(TVG_ENGINE_SW, 0);
}
#endif
lv_ll_init(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, sizeof(lv_draw_sw_custom_blend_handler_t));
+243
View File
@@ -8,7 +8,15 @@
*********************/
#include "blend/lv_draw_sw_blend_private.h"
#include "../lv_draw_label_private.h"
#include "../../draw/lv_draw_private.h"
#include "lv_draw_sw.h"
#if LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC
#include "../../libs/freetype/lv_freetype_private.h"
#endif
#if LV_USE_DRAW_SW
#include "../../display/lv_display.h"
@@ -35,6 +43,13 @@
static void /* LV_ATTRIBUTE_FAST_MEM */ draw_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_dsc,
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
#if LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC
static void freetype_outline_event_cb(lv_event_t * e);
static void draw_letter_outline(lv_draw_task_t * t, lv_draw_glyph_dsc_t * dsc);
#endif
/**********************
* STATIC VARIABLES
**********************/
@@ -84,6 +99,15 @@ void lv_draw_sw_label(lv_draw_task_t * t, const lv_draw_label_dsc_t * dsc, const
if(dsc->opa <= LV_OPA_MIN) return;
LV_PROFILER_DRAW_BEGIN;
#if LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC
static bool is_init = false;
if(!is_init) {
lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, t);
is_init = true;
}
#endif
lv_draw_label_iterate_characters(t, dsc, coords, draw_letter_cb);
LV_PROFILER_DRAW_END;
}
@@ -154,6 +178,13 @@ static void LV_ATTRIBUTE_FAST_MEM draw_letter_cb(lv_draw_task_t * t, lv_draw_gly
}
break;
}
break;
#if LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC
case LV_FONT_GLYPH_FORMAT_VECTOR: {
draw_letter_outline(t, glyph_draw_dsc);
}
break;
#endif
default:
break;
}
@@ -164,4 +195,216 @@ static void LV_ATTRIBUTE_FAST_MEM draw_letter_cb(lv_draw_task_t * t, lv_draw_gly
}
}
#if LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC
typedef struct {
lv_vector_path_t * inside_path; /*The regular glyph*/
lv_vector_path_t * outside_path; /*A bigger glyph that goes in the background for the letter outline*/
lv_vector_path_t * cur_path;
} lv_draw_sw_letter_outlines_t;
/*
* Renders the vectors paths representing a glyph with ThorVG
* the result is then blended into the draw buffer
*/
static void draw_letter_outline(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_dsc)
{
lv_draw_sw_letter_outlines_t * glyph_paths;
lv_vector_dsc_t * vector_dsc;
lv_draw_buf_t * draw_buf;
lv_matrix_t matrix;
lv_layer_t layer;
glyph_paths = (lv_draw_sw_letter_outlines_t *) glyph_dsc->glyph_data;
LV_ASSERT_NULL(glyph_paths);
int32_t cf;
int32_t w;
int32_t h;
uint32_t stride;
float scale;
lv_area_t buf_area;
cf = LV_COLOR_FORMAT_ARGB8888;
scale = LV_FREETYPE_F26DOT6_TO_FLOAT(lv_freetype_outline_get_scale(glyph_dsc->g->resolved_font));
w = (int32_t)((float) glyph_dsc->g->box_w + glyph_dsc->outline_stroke_width * 2 * scale);
h = (int32_t)((float) glyph_dsc->g->box_h + glyph_dsc->outline_stroke_width * 2 * scale);
buf_area.x1 = 0;
buf_area.y1 = 0;
lv_area_set_width(&buf_area, w);
lv_area_set_height(&buf_area, h);
stride = lv_draw_buf_width_to_stride(w, cf);
draw_buf = lv_draw_buf_create(w, h, cf, stride);
lv_draw_buf_clear(draw_buf, NULL);
lv_memzero(&layer, sizeof(lv_layer_t));
layer.draw_buf = draw_buf;
layer.color_format = cf;
layer.buf_area = buf_area;
layer.phy_clip_area = buf_area;
layer._clip_area = buf_area;
lv_memzero(&matrix, sizeof(lv_matrix_t));
lv_matrix_identity(&matrix);
vector_dsc = lv_vector_dsc_create(&layer);
int32_t offset_x;
int32_t offset_y;
offset_x = (int32_t)((float) glyph_dsc->g->ofs_x - glyph_dsc->outline_stroke_width * scale);
offset_y = (int32_t)((float) glyph_dsc->g->ofs_y - glyph_dsc->outline_stroke_width * scale);
/*Invert Y-Axis - Freetype's origin point is in the bottom left corner*/
lv_matrix_scale(&matrix, 1, -1);
lv_matrix_translate(&matrix, -offset_x, -h - offset_y);
lv_matrix_scale(&matrix, scale, scale);
lv_vector_dsc_set_transform(vector_dsc, &matrix);
/*Set attributes color, line width etc*/
if(cf == LV_COLOR_FORMAT_ARGB8888) {
if(glyph_dsc->outline_stroke_width > 0) {
lv_vector_dsc_set_fill_color(vector_dsc, glyph_dsc->outline_stroke_color);
lv_vector_dsc_set_fill_opa(vector_dsc, glyph_dsc->outline_stroke_opa);
lv_vector_dsc_add_path(vector_dsc, glyph_paths->outside_path);
}
lv_vector_dsc_set_fill_color(vector_dsc, glyph_dsc->color);
lv_vector_dsc_set_fill_opa(vector_dsc, glyph_dsc->opa);
lv_vector_dsc_add_path(vector_dsc, glyph_paths->inside_path);
}
else {
LV_LOG_ERROR("Unsupported color format: %d", cf);
}
lv_area_t old_area;
lv_area_t letter_coords;
/*Render vector path(s) - set the clip area so that it matches
*the size of the temporary buffer used to render the glyph path(s)*/
lv_memcpy(&old_area, &t->clip_area, sizeof(lv_area_t));
lv_memcpy(&t->clip_area, &buf_area, sizeof(lv_area_t));
lv_draw_vector(vector_dsc);
LV_ASSERT_NULL(layer.draw_task_head);
lv_draw_sw_vector(t, (lv_draw_vector_task_dsc_t *) layer.draw_task_head->draw_dsc);
/*Restore previous draw area of the entire text label*/
lv_memcpy(&t->clip_area, &old_area, sizeof(lv_area_t));
lv_memcpy(&letter_coords, glyph_dsc->letter_coords, sizeof(lv_area_t));
lv_area_set_width(&letter_coords, w);
lv_area_set_height(&letter_coords, h);
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.rotation = 0;
img_dsc.scale_x = LV_SCALE_NONE;
img_dsc.scale_y = LV_SCALE_NONE;
img_dsc.opa = LV_OPA_100;
img_dsc.src = draw_buf;
lv_draw_sw_image(t, &img_dsc, &letter_coords);
lv_vector_dsc_delete(vector_dsc);
lv_draw_buf_destroy(draw_buf);
}
/* Build the inside and outside vector paths for a glyph based
* on the recieved outline events emitted by lv_freetype_outline.c */
static void freetype_outline_event_cb(lv_event_t * e)
{
lv_fpoint_t pnt;
lv_fpoint_t ctrl_pnt1;
lv_fpoint_t ctrl_pnt2;
lv_draw_sw_letter_outlines_t * glyph_paths;
lv_vector_path_t * path;
lv_freetype_outline_event_param_t * outline_event;
outline_event = lv_event_get_param(e);
pnt.x = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->to.x);
pnt.y = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->to.y);
glyph_paths = outline_event->outline;
if(lv_event_get_code(e) == LV_EVENT_CREATE) {
glyph_paths = lv_malloc(sizeof(lv_draw_sw_letter_outlines_t));
LV_ASSERT_NULL(glyph_paths);
glyph_paths->cur_path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_HIGH);
glyph_paths->inside_path = glyph_paths->cur_path;
outline_event->outline = glyph_paths;
return;
}
else if(lv_event_get_code(e) == LV_EVENT_DELETE) {
if(glyph_paths->inside_path != NULL) {
lv_vector_path_clear(glyph_paths->inside_path);
lv_vector_path_delete(glyph_paths->inside_path);
}
if(glyph_paths->outside_path != NULL) {
lv_vector_path_clear(glyph_paths->outside_path);
lv_vector_path_delete(glyph_paths->outside_path);
}
lv_free(glyph_paths);
return;
}
else if(outline_event->type == LV_FREETYPE_OUTLINE_BORDER_START) {
/* Inside path is done - create the border path */
lv_vector_path_close(glyph_paths->cur_path);
glyph_paths->cur_path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_HIGH);
glyph_paths->outside_path = glyph_paths->cur_path;
return;
}
path = glyph_paths->cur_path;
switch(outline_event->type) {
case LV_FREETYPE_OUTLINE_MOVE_TO:
lv_vector_path_move_to(path, &pnt);
break;
case LV_FREETYPE_OUTLINE_LINE_TO:
lv_vector_path_line_to(path, &pnt);
break;
case LV_FREETYPE_OUTLINE_CUBIC_TO:
ctrl_pnt1.x = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control1.x);
ctrl_pnt1.y = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control1.y);
ctrl_pnt2.x = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control2.x);
ctrl_pnt2.y = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control2.y);
lv_vector_path_cubic_to(path, &ctrl_pnt1, &ctrl_pnt2, &pnt);
break;
case LV_FREETYPE_OUTLINE_CONIC_TO:
ctrl_pnt1.x = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control1.x);
ctrl_pnt1.y = LV_FREETYPE_F26DOT6_TO_FLOAT(outline_event->control1.y);
lv_vector_path_quad_to(path, &ctrl_pnt1, &pnt);
break;
case LV_FREETYPE_OUTLINE_END:
case LV_FREETYPE_OUTLINE_BORDER_START:
/* It's not necessary to close the path and
* border start is handled above
*/
break;
}
}
#endif /* LV_USE_FREETYPE && LV_USE_VECTOR_GRAPHIC */
#endif /*LV_USE_DRAW_SW*/
-1
View File
@@ -492,7 +492,6 @@ void lv_draw_sw_vector(lv_draw_task_t * t, const lv_draw_vector_task_dsc_t * dsc
buf = new_buf->data;
stride = new_buf->header.stride;
}
Tvg_Canvas * canvas = tvg_swcanvas_create();
tvg_swcanvas_set_target(canvas, buf, stride / 4, width, height, TVG_COLORSPACE_ARGB8888S);
+1
View File
@@ -68,6 +68,7 @@ typedef struct {
int16_t ofs_y; /**< y offset of the bounding box*/
lv_font_glyph_format_t format; /**< Font format of the glyph see lv_font_glyph_format_t */
uint8_t is_placeholder: 1; /**< Glyph is missing. But placeholder will still be displayed*/
int32_t outline_stroke_width; /**< used with freetype vector fonts - width of the letter outline */
/** 0: Get bitmap should return an A8 or ARGB8888 image.
* 1: return the bitmap as it is (Maybe A1/2/4 or any proprietary formats). */
+3 -1
View File
@@ -18,6 +18,8 @@ extern "C" {
#include "../../misc/lv_types.h"
#include "../../misc/lv_event.h"
#include "../../misc/lv_color.h"
#include LV_STDBOOL_INCLUDE
/*********************
@@ -56,6 +58,7 @@ typedef enum {
LV_FREETYPE_OUTLINE_LINE_TO,
LV_FREETYPE_OUTLINE_CUBIC_TO,
LV_FREETYPE_OUTLINE_CONIC_TO,
LV_FREETYPE_OUTLINE_BORDER_START, /* When line width > 0 the border glyph is drawn after the regular glyph */
} lv_freetype_outline_type_t;
/**********************
@@ -83,7 +86,6 @@ void lv_freetype_uninit(void);
*/
lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size,
lv_freetype_font_style_t style);
/**
* Delete a freetype font.
* @param font freetype font to be deleted.
+3 -3
View File
@@ -131,10 +131,9 @@ static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_
static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data)
{
LV_PROFILER_FONT_BEGIN;
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data;
FT_Error error;
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data;
lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc;
lv_mutex_lock(&dsc->cache_node->face_lock);
@@ -169,6 +168,7 @@ static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void
FT_GlyphSlot glyph = face->glyph;
if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) {
dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance);
dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/
dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/
@@ -177,7 +177,7 @@ static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void
glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/
dsc_out->format = LV_FONT_GLYPH_FORMAT_VECTOR;
/*Transform the glyph to italic if required*/
/*Transform the glyph to italic if required */
if(dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) {
dsc_out->box_w = lv_freetype_italic_transform_on_pos((lv_point_t) {
dsc_out->box_w, dsc_out->box_h
+112 -48
View File
@@ -33,7 +33,7 @@ typedef struct _lv_freetype_outline_node_t {
**********************/
static lv_freetype_outline_t outline_create(lv_freetype_context_t * ctx, FT_Face face, FT_UInt glyph_index,
uint32_t size, uint32_t strength);
uint32_t size, uint32_t strength, uint32_t border_width);
static lv_result_t outline_delete(lv_freetype_context_t * ctx, lv_freetype_outline_t outline);
static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf);
static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc);
@@ -128,7 +128,8 @@ static bool freetype_glyph_outline_create_cb(lv_freetype_outline_node_t * node,
dsc->cache_node->face,
node->glyph_index,
dsc->cache_node->ref_size,
dsc->style & LV_FREETYPE_FONT_STYLE_BOLD ? 1 : 0);
dsc->style & LV_FREETYPE_FONT_STYLE_BOLD ? 1 : 0,
dsc->outline_stroke_width);
lv_mutex_unlock(&dsc->cache_node->face_lock);
if(!outline) {
@@ -168,7 +169,11 @@ static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, lv
const lv_font_t * font = g_dsc->resolved_font;
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
dsc->outline_stroke_width = g_dsc->outline_stroke_width;
lv_cache_entry_t * entry = lv_freetype_outline_lookup(dsc, (FT_UInt)g_dsc->gid.index);
if(entry == NULL) {
return NULL;
}
@@ -300,11 +305,14 @@ static lv_freetype_outline_t outline_create(
FT_Face face,
FT_UInt glyph_index,
uint32_t size,
uint32_t strength)
uint32_t strength,
uint32_t border_width)
{
LV_PROFILER_FONT_BEGIN;
LV_ASSERT_NULL(ctx);
FT_Error error;
FT_Glyph glyph;
FT_Stroker stroker;
error = FT_Set_Pixel_Sizes(face, 0, size);
if(error) {
@@ -313,6 +321,7 @@ static lv_freetype_outline_t outline_create(
return NULL;
}
/**
* Disable AUTOHINT(https://freetype.org/autohinting/hinter.html) to avoid display clipping
* caused by inconsistent glyph measurement and outline.
@@ -331,6 +340,7 @@ static lv_freetype_outline_t outline_create(
}
}
FT_Outline_Funcs outline_funcs = {
.move_to = outline_move_to_cb,
.line_to = outline_line_to_cb,
@@ -340,42 +350,14 @@ static lv_freetype_outline_t outline_create(
.delta = 0
};
lv_result_t res;
lv_freetype_outline_event_param_t param;
lv_memzero(&param, sizeof(param));
/*Calculate Total Segments Before decompose */
int32_t tag_size = face->glyph->outline.n_points;
int32_t segments = 0;
int32_t vectors = 0;
for(int j = 0; j < tag_size; j++) {
if((face->glyph->outline.tags[j] & 0x1) == 0x1) {
segments++;
vectors++;
}
else {
int jj = j + 1 < tag_size ? j + 1 : 0;
if(face->glyph->outline.tags[jj] & 0x1) {
vectors++;
}
else {
segments++;
vectors += 2;
}
}
}
/*Also for every contour we may have a line for close*/
segments += face->glyph->outline.n_contours;
vectors += face->glyph->outline.n_contours;
param.sizes.data_size = vectors * 2;
param.sizes.segments_size = segments;
lv_freetype_outline_t outline;
res = outline_send_event(ctx, LV_EVENT_CREATE, &param);
lv_freetype_outline_t outline = param.outline;
outline = param.outline;
if(res != LV_RESULT_OK || !outline) {
LV_LOG_ERROR("Outline object create failed");
@@ -383,22 +365,104 @@ static lv_freetype_outline_t outline_create(
return NULL;
}
/* Run outline decompose again to fill outline data */
error = FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, outline);
if(error) {
FT_ERROR_MSG("FT_Outline_Decompose", error);
outline_delete(ctx, outline);
LV_PROFILER_FONT_END;
return NULL;
}
/* 1 iteration if there is no border */
/* 2 iterations if there is a a border and the glyph itsef */
for(int i = 0; i < (border_width > 0 ? 2 : 1); i++) {
/* close outline */
res = outline_push_point(outline, LV_FREETYPE_OUTLINE_END, NULL, NULL, NULL);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Outline object close failed");
outline_delete(ctx, outline);
LV_PROFILER_FONT_END;
return NULL;
FT_Outline glyph_outline;
if(i == 1) {
/* decompose the border glyph */
FT_Stroker_New(ctx->library, &stroker);
FT_Stroker_Set(stroker, border_width * 64,
FT_STROKER_LINECAP_ROUND,
FT_STROKER_LINEJOIN_ROUND,
0);
FT_Get_Glyph(face->glyph, &glyph);
FT_Glyph_StrokeBorder(&glyph, stroker, 0, true);
FT_OutlineGlyph g = (FT_OutlineGlyph) glyph;
FT_Stroker_Done(stroker);
glyph_outline = g->outline;
}
else {
/* decompose glyph */
glyph_outline = face->glyph->outline;
}
/*Calculate Total Segments Before decompose */
int32_t tag_size = glyph_outline.n_points;
int32_t segments = 0;
int32_t vectors = 0;
for(int j = 0; j < tag_size; j++) {
#if 0
if(j == 0 && (glyph_outline.tags[j] & 0x1) == 0) {
/* TODO handle the case where the first point is 'off curve' */
https://stackoverflow.com/questions/3465809/how-to-interpret-a-freetype-glyph-outline-when-the-first-point-on-the-contour-is
}
#endif
if((glyph_outline.tags[j] & 0x1) == 0x1) {
segments++;
vectors++;
}
else {
int jj = j + 1 < tag_size ? j + 1 : 0;
if(glyph_outline.tags[jj] & 0x1) {
vectors++;
}
else {
segments++;
vectors += 2;
}
}
}
/*Also for every contour we may have a line for close*/
segments += glyph_outline.n_contours;
vectors += glyph_outline.n_contours;
param.sizes.data_size = vectors * 2;
param.sizes.segments_size = segments;
/* Run outline decompose again to fill outline data */
error = FT_Outline_Decompose(&glyph_outline, &outline_funcs, outline);
if(error) {
FT_ERROR_MSG("FT_Outline_Decompose", error);
outline_delete(ctx, outline);
LV_PROFILER_FONT_END;
return NULL;
}
if(i == 0 && border_width > 0) {
/* Close the border glyph before decomposing the inside glyph */
res = outline_push_point(outline, LV_FREETYPE_OUTLINE_BORDER_START, NULL, NULL, NULL);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Outline object close failed");
outline_delete(ctx, outline);
LV_PROFILER_FONT_END;
return NULL;
}
}
else if(i == 0 || (i == 1 && border_width > 0)) {
/* Close the border glyph or the regular glyph */
res = outline_push_point(outline, LV_FREETYPE_OUTLINE_END, NULL, NULL, NULL);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Outline object close failed");
outline_delete(ctx, outline);
LV_PROFILER_FONT_END;
return NULL;
}
}
}
LV_PROFILER_FONT_END;
+2
View File
@@ -28,6 +28,7 @@ extern "C" {
#include FT_SIZES_H
#include FT_IMAGE_H
#include FT_OUTLINE_H
#include FT_STROKER_H
/*********************
* DEFINES
@@ -119,6 +120,7 @@ typedef struct _lv_freetype_font_dsc_t {
lv_freetype_cache_node_t * cache_node;
lv_cache_entry_t * cache_node_entry;
FTC_FaceID face_id;
uint32_t outline_stroke_width;
} lv_freetype_font_dsc_t;
/**********************
+1
View File
@@ -13,3 +13,4 @@
#define THORVG_VERSION_STRING "0.15.3"
#define THORVG_THREAD_SUPPORT
+43 -40
View File
@@ -238,50 +238,53 @@ enum {
LV_STYLE_TEXT_LINE_SPACE = 92,
LV_STYLE_TEXT_DECOR = 93,
LV_STYLE_TEXT_ALIGN = 94,
LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH = 95,
LV_STYLE_TEXT_OUTLINE_STROKE_OPA = 96,
LV_STYLE_TEXT_OUTLINE_STROKE_COLOR = 97,
LV_STYLE_OPA = 95,
LV_STYLE_OPA_LAYERED = 96,
LV_STYLE_COLOR_FILTER_DSC = 97,
LV_STYLE_COLOR_FILTER_OPA = 98,
LV_STYLE_ANIM = 99,
LV_STYLE_ANIM_DURATION = 100,
LV_STYLE_TRANSITION = 102,
LV_STYLE_BLEND_MODE = 103,
LV_STYLE_TRANSFORM_WIDTH = 104,
LV_STYLE_TRANSFORM_HEIGHT = 105,
LV_STYLE_TRANSLATE_X = 106,
LV_STYLE_TRANSLATE_Y = 107,
LV_STYLE_TRANSFORM_SCALE_X = 108,
LV_STYLE_TRANSFORM_SCALE_Y = 109,
LV_STYLE_TRANSFORM_ROTATION = 110,
LV_STYLE_TRANSFORM_PIVOT_X = 111,
LV_STYLE_TRANSFORM_PIVOT_Y = 112,
LV_STYLE_TRANSFORM_SKEW_X = 113,
LV_STYLE_TRANSFORM_SKEW_Y = 114,
LV_STYLE_BITMAP_MASK_SRC = 115,
LV_STYLE_ROTARY_SENSITIVITY = 116,
LV_STYLE_TRANSLATE_RADIAL = 117,
LV_STYLE_RECOLOR = 118,
LV_STYLE_RECOLOR_OPA = 119,
LV_STYLE_OPA = 98,
LV_STYLE_OPA_LAYERED = 99,
LV_STYLE_COLOR_FILTER_DSC = 100,
LV_STYLE_COLOR_FILTER_OPA = 101,
LV_STYLE_ANIM = 102,
LV_STYLE_ANIM_DURATION = 103,
LV_STYLE_TRANSITION = 104,
LV_STYLE_BLEND_MODE = 105,
LV_STYLE_TRANSFORM_WIDTH = 106,
LV_STYLE_TRANSFORM_HEIGHT = 107,
LV_STYLE_TRANSLATE_X = 108,
LV_STYLE_TRANSLATE_Y = 109,
LV_STYLE_TRANSFORM_SCALE_X = 110,
LV_STYLE_TRANSFORM_SCALE_Y = 111,
LV_STYLE_TRANSFORM_ROTATION = 112,
LV_STYLE_TRANSFORM_PIVOT_X = 113,
LV_STYLE_TRANSFORM_PIVOT_Y = 114,
LV_STYLE_TRANSFORM_SKEW_X = 115,
LV_STYLE_TRANSFORM_SKEW_Y = 116,
LV_STYLE_BITMAP_MASK_SRC = 117,
LV_STYLE_ROTARY_SENSITIVITY = 118,
LV_STYLE_TRANSLATE_RADIAL = 119,
LV_STYLE_RECOLOR = 120,
LV_STYLE_RECOLOR_OPA = 121,
LV_STYLE_FLEX_FLOW = 125,
LV_STYLE_FLEX_MAIN_PLACE = 126,
LV_STYLE_FLEX_CROSS_PLACE = 127,
LV_STYLE_FLEX_TRACK_PLACE = 128,
LV_STYLE_FLEX_GROW = 129,
LV_STYLE_FLEX_FLOW = 122,
LV_STYLE_FLEX_MAIN_PLACE = 123,
LV_STYLE_FLEX_CROSS_PLACE = 124,
LV_STYLE_FLEX_TRACK_PLACE = 125,
LV_STYLE_FLEX_GROW = 126,
LV_STYLE_GRID_COLUMN_ALIGN = 130,
LV_STYLE_GRID_ROW_ALIGN = 131,
LV_STYLE_GRID_ROW_DSC_ARRAY = 132,
LV_STYLE_GRID_COLUMN_DSC_ARRAY = 133,
LV_STYLE_GRID_CELL_COLUMN_POS = 134,
LV_STYLE_GRID_CELL_COLUMN_SPAN = 135,
LV_STYLE_GRID_CELL_X_ALIGN = 136,
LV_STYLE_GRID_CELL_ROW_POS = 137,
LV_STYLE_GRID_CELL_ROW_SPAN = 138,
LV_STYLE_GRID_CELL_Y_ALIGN = 139,
LV_STYLE_GRID_COLUMN_ALIGN = 127,
LV_STYLE_GRID_ROW_ALIGN = 128,
LV_STYLE_GRID_ROW_DSC_ARRAY = 129,
LV_STYLE_GRID_COLUMN_DSC_ARRAY = 130,
LV_STYLE_GRID_CELL_COLUMN_POS = 131,
LV_STYLE_GRID_CELL_COLUMN_SPAN = 132,
LV_STYLE_GRID_CELL_X_ALIGN = 133,
LV_STYLE_GRID_CELL_ROW_POS = 134,
LV_STYLE_GRID_CELL_ROW_SPAN = 135,
LV_STYLE_GRID_CELL_Y_ALIGN = 136,
LV_STYLE_LAST_BUILT_IN_PROP = 140,
LV_STYLE_LAST_BUILT_IN_PROP = 137,
LV_STYLE_NUM_BUILT_IN_PROPS = LV_STYLE_LAST_BUILT_IN_PROP + 1,
+24
View File
@@ -674,6 +674,30 @@ void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value)
lv_style_set_prop(style, LV_STYLE_TEXT_ALIGN, v);
}
void lv_style_set_text_outline_stroke_color(lv_style_t * style, lv_color_t value)
{
lv_style_value_t v = {
.color = value
};
lv_style_set_prop(style, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR, v);
}
void lv_style_set_text_outline_stroke_width(lv_style_t * style, int32_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH, v);
}
void lv_style_set_text_outline_stroke_opa(lv_style_t * style, lv_opa_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_TEXT_OUTLINE_STROKE_OPA, v);
}
void lv_style_set_radius(lv_style_t * style, int32_t value)
{
lv_style_value_t v = {
+18
View File
@@ -97,6 +97,9 @@ void lv_style_set_text_letter_space(lv_style_t * style, int32_t value);
void lv_style_set_text_line_space(lv_style_t * style, int32_t value);
void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value);
void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value);
void lv_style_set_text_outline_stroke_color(lv_style_t * style, lv_color_t value);
void lv_style_set_text_outline_stroke_width(lv_style_t * style, int32_t value);
void lv_style_set_text_outline_stroke_opa(lv_style_t * style, lv_opa_t value);
void lv_style_set_radius(lv_style_t * style, int32_t value);
void lv_style_set_radial_offset(lv_style_t * style, int32_t value);
void lv_style_set_clip_corner(lv_style_t * style, bool value);
@@ -551,6 +554,21 @@ void lv_style_set_grid_cell_row_span(lv_style_t * style, int32_t value);
.prop = LV_STYLE_TEXT_ALIGN, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_TEXT_OUTLINE_STROKE_COLOR(val) \
{ \
.prop = LV_STYLE_TEXT_OUTLINE_STROKE_COLOR, .value = { .color = val } \
}
#define LV_STYLE_CONST_TEXT_OUTLINE_STROKE_WIDTH(val) \
{ \
.prop = LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_TEXT_OUTLINE_STROKE_OPA(val) \
{ \
.prop = LV_STYLE_TEXT_OUTLINE_STROKE_OPA, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_RADIUS(val) \
{ \
.prop = LV_STYLE_RADIUS, .value = { .num = (int32_t)val } \
+8
View File
@@ -430,6 +430,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool
const int32_t letter_height = lv_font_get_line_height(font);
int32_t y = 0;
lv_text_flag_t flag = get_label_flags(label);
/*Search the line of the index letter*/;
@@ -775,6 +776,7 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e)
if(label->invalid_size_cache) {
const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);
lv_text_flag_t flag = LV_TEXT_FLAG_NONE;
if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR;
@@ -840,6 +842,12 @@ static void draw_main(lv_event_t * e)
label_draw_dsc.sel_bg_color = lv_obj_get_style_bg_color(obj, LV_PART_SELECTED);
}
/* get the style attributes of a letter outline */
label_draw_dsc.outline_stroke_color = lv_obj_get_style_text_outline_stroke_color(obj, LV_PART_MAIN);
label_draw_dsc.outline_stroke_opa = lv_obj_get_style_text_outline_stroke_opa(obj, LV_PART_MAIN);
label_draw_dsc.outline_stroke_width = lv_obj_get_style_text_outline_stroke_width(obj, LV_PART_MAIN);
/* In SCROLL and SCROLL_CIRCULAR mode the CENTER and RIGHT are pointless, so remove them.
* (In addition, they will create misalignment in this situation)*/
if((label->long_mode == LV_LABEL_LONG_MODE_SCROLL || label->long_mode == LV_LABEL_LONG_MODE_SCROLL_CIRCULAR) &&
+1 -1
View File
@@ -18,7 +18,7 @@
extern const lv_property_name_t lv_obj_property_names[73];
extern const lv_property_name_t lv_roller_property_names[3];
extern const lv_property_name_t lv_slider_property_names[8];
extern const lv_property_name_t lv_style_property_names[117];
extern const lv_property_name_t lv_style_property_names[120];
extern const lv_property_name_t lv_textarea_property_names[15];
#endif
#endif
+4 -1
View File
@@ -14,7 +14,7 @@
* Generated code from properties.py
*/
/* *INDENT-OFF* */
const lv_property_name_t lv_style_property_names[117] = {
const lv_property_name_t lv_style_property_names[120] = {
{"align", LV_PROPERTY_STYLE_ALIGN,},
{"anim", LV_PROPERTY_STYLE_ANIM,},
{"anim_duration", LV_PROPERTY_STYLE_ANIM_DURATION,},
@@ -116,6 +116,9 @@ const lv_property_name_t lv_style_property_names[117] = {
{"text_letter_space", LV_PROPERTY_STYLE_TEXT_LETTER_SPACE,},
{"text_line_space", LV_PROPERTY_STYLE_TEXT_LINE_SPACE,},
{"text_opa", LV_PROPERTY_STYLE_TEXT_OPA,},
{"text_outline_stroke_color", LV_PROPERTY_STYLE_TEXT_OUTLINE_STROKE_COLOR,},
{"text_outline_stroke_opa", LV_PROPERTY_STYLE_TEXT_OUTLINE_STROKE_OPA,},
{"text_outline_stroke_width", LV_PROPERTY_STYLE_TEXT_OUTLINE_STROKE_WIDTH,},
{"transform_height", LV_PROPERTY_STYLE_TRANSFORM_HEIGHT,},
{"transform_pivot_x", LV_PROPERTY_STYLE_TRANSFORM_PIVOT_X,},
{"transform_pivot_y", LV_PROPERTY_STYLE_TRANSFORM_PIVOT_Y,},
@@ -113,6 +113,9 @@ enum {
LV_PROPERTY_ID(STYLE, TEXT_LETTER_SPACE, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_LETTER_SPACE),
LV_PROPERTY_ID(STYLE, TEXT_LINE_SPACE, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_LINE_SPACE),
LV_PROPERTY_ID(STYLE, TEXT_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_OPA),
LV_PROPERTY_ID(STYLE, TEXT_OUTLINE_STROKE_COLOR, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_OUTLINE_STROKE_COLOR),
LV_PROPERTY_ID(STYLE, TEXT_OUTLINE_STROKE_OPA, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_OUTLINE_STROKE_OPA),
LV_PROPERTY_ID(STYLE, TEXT_OUTLINE_STROKE_WIDTH, LV_PROPERTY_TYPE_INT, LV_STYLE_TEXT_OUTLINE_STROKE_WIDTH),
LV_PROPERTY_ID(STYLE, TRANSFORM_HEIGHT, LV_PROPERTY_TYPE_INT, LV_STYLE_TRANSFORM_HEIGHT),
LV_PROPERTY_ID(STYLE, TRANSFORM_PIVOT_X, LV_PROPERTY_TYPE_INT, LV_STYLE_TRANSFORM_PIVOT_X),
LV_PROPERTY_ID(STYLE, TRANSFORM_PIVOT_Y, LV_PROPERTY_TYPE_INT, LV_STYLE_TRANSFORM_PIVOT_Y),