takkaO / OpenFontRender

TTF font render support library for microcomputer.
Other
118 stars 16 forks source link

OpenFontRender support for Teensy 4.1 #45

Open hnikolov opened 6 months ago

hnikolov commented 6 months ago

Hello, OpenFontRender is great, compliments for that! I am using OpenFontRender together with TFT_eSPI library (2.5.43). Using Arduino IDE 2.3.2, I can build the Noto_Font_Demo (https://github.com/takkaO/OpenFontRender/tree/master/examples/TFT_eSPI/Noto_Font_Demo) and run it on ESP32 board using a TFT with an ILI9341 controller. Unfortunately, I cannot compile the same for a Teensy board (tried versions 3.1, 3.6, 4.1).

I get a linker error, please see below (a few warnings first and the error is at the bottom). I could not figure out what the problem is. Help fixing this is highly appreciated because I would like to use OpenFontRender in a project with a Teensy board. Note: Without OpenFontRender, I can successfully build and run projects with Teensy 4.1 (1.59.0), TFT_eSPI (2.5.43), and the same TFT display.

Output from Arduino IDE 2.3.2 \arduino\libraries\OpenFontRender\src\sfnt\ttcmap.c:55:3: warning: 'tt_cmap_init' defined but not used [-Wunused-function] 55 | tt_cmap_init( TT_CMap cmap,

\arduino\libraries\OpenFontRender\src\OpenFontRender.cpp: In member function 'uint16_t OpenFontRender::drawHString(const char*, int32_t, int32_t, uint16_t, uint16_t, Align, Drawing, FT_BBox&, FT_Error&)': \arduino\libraries\OpenFontRender\src\OpenFontRender.cpp:774:75: warning: comparison of integer expressions of different signedness: 'int32_t' {aka 'long int'} and 'long unsigned int' [-Wsign-compare] 774 | if (_saved_state.drawn_bg_point.x < (pos.x + (uint32_t)bit->bitmap.width)) {

\arduino\libraries\OpenFontRender\src\OpenFontRender.cpp: In member function 'void OpenFontRender::draw2screen(FT_BitmapGlyph, uint32_t, uint32_t, uint16_t, uint16_t)': \arduino\libraries\OpenFontRender\src\OpenFontRender.cpp:1431:83: warning: comparison of integer expressions of different signedness: 'int32_t' {aka 'long int'} and 'long unsigned int' [-Wsign-compare] 1431 | if (_saved_state.drawn_bg_point.x <= (x + _x)) {

\arduino\libraries\OpenFontRender\src\OpenFontRender.cpp:1462:75: warning: comparison of integer expressions of different signedness: 'int32_t' {aka 'long int'} and 'long unsigned int' [-Wsign-compare] 1462 | if (_saved_state.drawn_bg_point.x <= (x + _x)) {

\arduino\libraries\OpenFontRender\src\OpenFontRender.cpp: In member function 'FT_Error OpenFontRender::loadFont(const char, uint8_t)': \arduino\libraries\OpenFontRender\src\OpenFontRender.cpp:446:16: warning: 'char strncpy(char, const char, size_t)' output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] 446 | strncpy(_face_id.filepath, fpath, len);

\arduino\libraries\OpenFontRender\src\OpenFontRender.cpp:443:28: note: length computed here 443 | size_t len = strlen(fpath);

/arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: /arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/thumb/v7e-m+dp/hard\libc.a(libc_a-openr.o): in function `_open_r':

(.text._open_r+0x14): undefined reference to `_open' collect2.exe: error: ld returned 1 exit status

exit status 1 Compilation error: exit status 1

alba-ado commented 6 months ago

I have the same issue with esp-idf v4.4

alba-ado commented 6 months ago

Changing the strncpy to memcpy seems to solve the issue. But I don't know how good of a fix this is. There could be a better method.

takkaO commented 6 months ago

@hnikolov , @alba-ado

I tried it with Arduino 2.3.2 + Teensy 4.1 and it compiled (I don't have Teensy, so I haven't verified that it works).

It may be because I used OpenFontRender v1.2.
Please re-test with v1.2 and if it fails, let me know a more detailed reproduction environment.

Thank you.

alba-ado commented 6 months ago

Hello, unfortunately, the issue persists. I was using the master branch, and now tested with the release with tag v1.2 and the error is the same. I have come across this error before with some other code I wrote. You are probably not getting this error because the Arduino is using an older version of the GCC. I am using -std=gnu++2a and some warnings are treated as errors. The error basically complains that the string is truncated because a null terminator copied as a character from the string before the string ends. For myself, I replaced it with memcpy since you are already null terminating the string, but I never loaded the font from a file so I don't know if it works. My board is ESP32-S3 and uses the IDF version v4.4 with Arduino core as a component. Here are the output logs:

/home/ado/Projects/Espressif/ui-test/components/OpenFontRender/src/OpenFontRender.cpp: In member function 'FT_Error OpenFontRender::loadFont(const char*, uint8_t)':
/home/ado/Projects/Espressif/ui-test/components/OpenFontRender/src/OpenFontRender.cpp:446:9: error: 'char* strncpy(char*, const char*, size_t)' output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation]
  strncpy(_face_id.filepath, fpath, len);
  ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/ado/Projects/Espressif/ui-test/components/OpenFontRender/src/OpenFontRender.cpp:443:21: note: length computed here
  size_t len = strlen(fpath);
               ~~~~~~^~~~~~~
cc1plus: some warnings being treated as errors

Edit:

Here is a discussion related to this issue:

https://stackoverflow.com/questions/1453876/why-does-strncpy-not-null-terminate

I fell like replacing it with memcpy seems safe since you are manually null-terminating the string. But using strncat would be the preferred solution.

takkaO commented 6 months ago

@alba-ado

The compilation completed successfully in my esp-idf 4.4 environment. Perhaps the reason it worked is that I did not specify the -std=gnu++2a option. However, I do not know where to specify this option on the IDE. Is there any documentation or web site available for set this option?

Thank you.

alba-ado commented 6 months ago

You add it to the CMakeLists.txt file inside the main folder. Mine is like this:

component_compile_options(-Wno-unknown-pragmas -Wno-missing-field-initializers -std=gnu++2a)

Be careful that it is not the one in the project folder, but the main folder inside the project folder.

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/cplusplus.html

takkaO commented 6 months ago

@alba-ado

I tried in my environment and did not encounter any errors. Look at the screenshot, are the settings in CMakeLists.txt correct?

スクリーンショット 2024-05-10 232212

I don't know if my settings are wrong or if I need to set something else in the IDE. If it is possible, can you provide a project that can reproduce the state?

Thank you.

alba-ado commented 6 months ago

Looks correct but I don't know what differs from my project to yours. I will make an example and put it on GitHub for you to try. In the meantime, I see that you have some warnings. The problem might be hidden in those warnings. Try adding -Werror flag to treat all warnings as errors so you could see it.

alba-ado commented 6 months ago

Here is the minimal project sample I created that replicates the issue on my machine (Ubuntu Linux 22.04 with ESP-IDF v4.4)

https://github.com/alba-ado/ofr-ui-demo

alba-ado commented 6 months ago

Another issue that comes to my mind, is that you using Eclipse or whatever IDE could be giving additional arguments to the compiler. Thus, suppressing the errors. I say we replace the strncpy with memcpy and call it a day. The code compiles that way and it seems safe to me. The only thing is that I can’t test the function by loading a font file from a file system. Perhaps you could test that. But I believe it will probably work. We just replace it with memcpy and won’t be wasting your time with this issue. I can open a pull request if you’d like, and you can test it.

takkaO commented 6 months ago

@alba-ado

Thanks for providing the sample project! I don't know what is causing the error, but I was able to reproduce the error when build the repository you provided. I will try to fix this issue.

hnikolov commented 6 months ago

@hnikolov , @alba-ado

I tried it with Arduino 2.3.2 + Teensy 4.1 and it compiled (I don't have Teensy, so I haven't verified that it works).

It may be because I used OpenFontRender v1.2. Please re-test with v1.2 and if it fails, let me know a more detailed reproduction environment.

Thank you.

Thank you for the hint! I confirm that the linker error is gone if I use OpenFontRender v1.2! 👍 Unfortunately, I was not able to test the Noto_Font_Demo on my Teensy HW yet. If I manage to test, I will confirm separately.

What I quickly did though was adding OpenFontRender to my target project and trying compiling it. To my surprise, I run out of memory :( Can you please check below and give some more info about the OpenFontRender memory requirements in general? Is the issue here related to the size of the font data? I am trying to load NotoSans_Bold font from the demo (NotoSans_Bold.h) Thanks a lot!!!

Without OpenFontRender

Memory Usage on Teensy 4.1: FLASH: code:400404, data:77716, headers:8276 free for files:7640068 RAM1: variables: 46496, code: 397644, padding: 28340 free for local variables: 51808 RAM2: variables:12416 free for malloc/new:511872

With OpenFontRender

Memory Usage on Teensy 4.1: FLASH: code:466848, data:84884, headers:8392 free for files:7566340 RAM1: variables: 54880, code:464088, padding: 27432 free for local variables: -22112 RAM2: variables:12416 free for malloc/new:511872 Error program exceeds memory space

hnikolov commented 6 months ago

@takkaO Hi again, I just found out that the relatively large (for an embedded system) memory requirement comes from the OpenFontRender loadFont() function. Regardless of the size of the font to be loaded, it uses ~60-70KB of memory. I checked with the Noto_Font_Demo by commenting out the load function. Maybe not needed, but I also used an alternative font (size=300KB) and got the same results. Is there a way to use less memory?

OpenFontRenderer: Noto_Font_Demo with loading the NotoSans_Bold font

Memory Usage on Teensy 4.1: FLASH: code:158312, data:45244, headers:8408 free for files:7914500 RAM1: variables: 20128, code: 155608, padding: 8232 free for local variables: 340320 RAM2: variables:12416 free for malloc/new:511872

OpenFontRenderer: Noto_Font_Demo without loading the NotoSans_Bold font

Memory Usage on Teensy 4.1: FLASH: code:103240, data:27472, headers:8548 free for files:7987204 RAM1: variables: 13984, code: 100536, padding: 30536 free for local variables: 379232 RAM2: variables:12416 free for malloc/new:511872

Thank you for the support!

alba-ado commented 6 months ago

@takkaO Hi again, I just found out that the relatively large (for an embedded system) memory requirement comes from the OpenFontRender loadFont() function. Regardless of the size of the font to be loaded, it uses ~60-70KB of memory. I checked with the Noto_Font_Demo by commenting out the load function. Maybe not needed, but I also used an alternative font (size=300KB) and got the same results. Is there a way to use less memory?

OpenFontRenderer: Noto_Font_Demo with loading the NotoSans_Bold font

Memory Usage on Teensy 4.1: FLASH: code:158312, data:45244, headers:8408 free for files:7914500 RAM1: variables: 20128, code: 155608, padding: 8232 free for local variables: 340320 RAM2: variables:12416 free for malloc/new:511872

OpenFontRenderer: Noto_Font_Demo without loading the NotoSans_Bold font

Memory Usage on Teensy 4.1: FLASH: code:103240, data:27472, headers:8548 free for files:7987204 RAM1: variables: 13984, code: 100536, padding: 30536 free for local variables: 379232 RAM2: variables:12416 free for malloc/new:511872

Thank you for the support!

I think you should open a separate issue for that

takkaO commented 6 months ago

@alba-ado

I have modified the code based on the sample code you provided. Due to errors outside of this library, I were not able to build it completely, but at least the errors reported in #45 should have been resolved.

The code is currently uploaded on the alpha branch. Please validate and provide feedback.

Thank you.

alba-ado commented 5 months ago

Hello, I confirm it to be working on my end. But I think you should also test it by loading the fonts from the file system. Since my fonts are in the code, it doesn't use that function.