Lv_freetype: bold/italic rendering

I think it will be cool to make lv_freetype able to render bold, italic and bold&&italic fonts. I know that it will be usable only if lv_freetype is used but anyway it will be usefull.

I think glyph can be transformed to italic even without lv_freetype by using matrix transformation like one used in AROMA Installer/Filemanager:
if (italic) {
FT_Matrix matrix;
matrix.xx = 0x10000L;
matrix.xy = 0x5000L;
matrix.yx = 0;
matrix.yy = 0x10000L;
FT_Glyph_Transform(glyph, &matrix, NULL);
}

Hi,

Sounds interesting. If it can work on the bitmaps of the built-in fonts we can consider adding it to the core library too.

Would you like to give it try?

I think I can not. A code is a bit too difficult. And FT_Glyph_Transform function’s code uses assembler code described in ftcalc.h.

I think bold font can be emulated by tripling a char with moving the second one a bit left (one or two pixels) and the second one a bit right. It can use DPI to calculate how much difference should be in coordinates.

The problem I see with this approach is that bold fonts will take longer to render than regular ones, as the glyph needs to be processed 2-3 times instead of once.

I do not think so. Glyphs are rendered dot by dot, one after another. We can try to render three points at once.

Maybe there is an algorithm for image tilt but I can not find it.

It’s sounds kind of hacky. Bold fonts are different fonts and not “derived” from the default font. However, “oblique” fonts are created from the “normal” font by calculation.

I just realized that “oblique” and “italic” are 2 different things however sometimes (usually?) they look the same. See:

Maybe we can try to implement oblique text? Or I need to implement bold/oblique/underlined/normal text rendering on my own?

Sorry for the late answer.

Adding oblique support could work IMO. The quality is still questionable. Can you make some experiments on a simple byte array of one letter?

Of course. Method of making text tilted is quite simple, but it needs to be optimized. Freetype uses assembly code to calculate mulfix.
lv_terminal.zip (89.4 KB)
Also I found an Embolden method of glyph which makes bold-like glyph derived from default font. We can try to use it. But it is a bit complicated.


I did not find a simple font-to-array function, so uGUI is used to render font.
And I know that my code is ugly, it is only proof of concept.

Great work @twaik!

In the attached zip I couldn’t find the code of the transformation. I suppose there should be an lv_console.c in it once lv_console.h is included in lv_terminal.c.

Would it be possible to use some kind of anti-aliasing? I.e. take the neighbour pixels into account too.
E.g. if on x=10, x=13.1 should be placed, a small amount from x=12 should be mixed to the final color too. In case of x=13.5 only x = 13 need to be used.

Sorry, wrong zip.
lv_oblique_test.zip (90.3 KB)

Algorythm does not render colours, only new point position or matrix of points. You can try it in lv_draw_letter_* function.

Thanks.

I see, however if we could see the fractional positions we could mix the colors of the target positions to get smoother edges. E.g. for “move 13.2 to 24” we could mix the colors under 12 (let’s say white) and 13 (black) according to the fractional part (0.2 -> almost fully 13 but a little bit from 12). So finally set dark gray.

Without anti-aliasing the edges will be jagged.

void make_oblique(void) takes original coordinates and modifies them according to transformation matrix. You can use double type to get more accurate position. This algorithm is used to move pixels. You can try to move position of pixel and apply blending coefficient used in original position to the final position.

You can try to modify map_p according to my algorythm in lv_draw_letter.

I’m thinking about how to add this to LVGL.

The goal is to keep LVGL lean for small footprint, easier maintenance. So it could be an external library similarly to lv_lib_png.

In this case, this functionality should be added to the font’s get_glyph_bitmap callback. What do you think?

The algorythm itself contains only three functions:

signed long mulfix(signed long a, signed long b);
void vector_transform(vec* v, matrix* m);
void make_oblique(void);

with less 21 lines of code. It can be easyly reimplemented as part of LVGL project and be applied to text as style. I do not think it will enlarge LVGL’s footprint.