Skip to content

Commit 6c8a164

Browse files
committed
Handle OOM gracefully with a fallback font
1 parent da973e5 commit 6c8a164

3 files changed

Lines changed: 17 additions & 10 deletions

File tree

‎doc/ExternalResources.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ lv_img_set_src(logo, "F:/images/logo.bin");
5555

5656
Load a font from the external resources.
5757

58-
You don't need to check if it exists in the constructor as LVGL can handle the font not existing gracefully (nothing will render).
58+
You don't need to check if it exists in the constructor a missing font is handled gracefully (a fallback font will be used, which is currently the main system font). If memory allocation fails the fallback font will also be used.
5959
However, do check that it exists in the `IsAvailable()` method so users can see when resources are missing (the watchface will not be selectable in the list if `IsAvailable()` returns `false`).
6060
The fonts will free themselves when the owning object is destructed.
6161

‎src/displayapp/fonts/FastFont.cpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ FastFont::Font FastFont::LoadFont(Pinetime::Controllers::FS& filesystem, const c
2626
lfs_file_t file;
2727
ret = filesystem.FileOpen(&file, fontPath, LFS_O_RDONLY);
2828
if (ret < 0) {
29-
return nullptr;
29+
return FastFont::Font(FallbackFont);
3030
}
3131
// Can use stat to get the size, but since the file is open we can grab it from there
3232
lfs_size_t size = file.ctz.size;
33-
auto fontData = std::make_unique_for_overwrite<uint8_t[]>(size);
34-
if (fontData.get() == nullptr) {
33+
auto fontData = std::unique_ptr<uint8_t[]>(static_cast<uint8_t*>(malloc(size)));
34+
if (fontData == nullptr) {
3535
filesystem.FileClose(&file);
36-
return nullptr;
36+
return FastFont::Font(FallbackFont);
3737
}
3838
ret = filesystem.FileRead(&file, fontData.get(), size);
3939
filesystem.FileClose(&file);
4040
if (ret != static_cast<int>(size)) {
41-
return nullptr;
41+
return FastFont::Font(FallbackFont);
4242
}
4343
auto* font = reinterpret_cast<lv_font_t*>(fontData.get());
4444
auto base = reinterpret_cast<uintptr_t>(fontData.get());

‎src/displayapp/fonts/FastFont.h‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@
66
namespace Pinetime {
77
namespace Components {
88
namespace FastFont {
9+
static constexpr const lv_font_t* FallbackFont = &jetbrains_mono_42;
10+
911
// Since the font pointer is actually a u8 array containing all loaded font data
1012
// we need to use the deleter for the true datatype rather than the single struct
1113
struct CastingDeleter {
12-
void operator()(lv_font_t* fontData) const {
13-
auto* fontDataReal = reinterpret_cast<uint8_t*>(fontData);
14-
std::default_delete<uint8_t[]> {}(fontDataReal);
14+
void operator()(const lv_font_t* fontData) const {
15+
// Don't try to free the fallback!
16+
if (fontData == FallbackFont) {
17+
return;
18+
}
19+
const auto* fontDataReal = reinterpret_cast<const uint8_t*>(fontData);
20+
std::default_delete<const uint8_t[]> {}(fontDataReal);
1521
}
1622
};
1723

18-
using Font = std::unique_ptr<lv_font_t, CastingDeleter>;
24+
using Font = std::unique_ptr<const lv_font_t, CastingDeleter>;
25+
// Returns a fallback if loading fails
1926
Font LoadFont(Pinetime::Controllers::FS& filesystem, const char* fontPath);
2027
}
2128
}

0 commit comments

Comments
 (0)