【LvGL】フォントの使い方・カスタムフォントの導入
LvGL のフォントについてわかったことまとめ
夫れ日本人ならば、日本語が表示されるか否かについて気になるのは、当然のことである。将、デザインに趣向を凝らすならば、任意のフォントが使えるか否かについて注意を向けることもまた、当然のことであろう。
本記事では、
フォントの使い方
上はバージョン7.11
の情報である。サイズが異なるだけのものも計数に含むと、概ね
しかし、初期状態では「
フォントを有効にする
フォントに関する設定の箇所
上に引用する通り、LV_FONT_MONTSERRAT_16
のみ1
とあり、それ以外の全てが0
となっている。なおこのLV_FONT_MONTSERRAT_16
は、「
default fontの記載
このような1
または0
の違いが意味するところは、次の箇所から分かる。
フォントの宣言箇所
下に引用した宣言の箇所は、このような記述となっている。
#if LV_FONT_⋯ // 条件分岐:「`LV_FONT_⋯`が`1`ならば」
LV_FONT_DECLARE(lv_font_⋯) // `lv_font_⋯`として宣言され、フォントが有効になる
#endif // 条件分岐終了
ここで、LV_FONT_MONTSERRAT_16
以外は全て0
であるから、この条件分岐に該当せず、LV_FONT_DECLARE
によって宣言されないため、無効になるのである。
参考:LV_FONT_DECLARE
の定義
まとめると、このように云える。
LV_FONT_⋯ の値 |
フォントの有効性 |
---|---|
0 |
無効 |
1 |
有効 |
これを念頭に、使用したいフォントについて0
を1
に変更すればよい。
なお、この設定はlv_conf_internal.h
というファイルに存在する。
参考:各ライブラリー毎の位置
-
Seeed_Arduino_LvGL
Seeed_Arduino_LvGL/src/src/lv_conf_internal.h
-
lvgl
lvgl/src/lv_conf_internal.h
何故フォントが無効になっているのか
以上に述べた通り設定を変更すれば済むとはいえ、そもそも何故設定を変更しなければ使えないようになっているのだろうか。
その答えは単純に、「フォントを使うだけ嵩張るから」であろうと考えられる。
参考:性能比較
例に
項目 | 数値 |
---|---|
Program Memory Size |
512KB |
External Flash |
4MB |
RAM Size |
192KB |
(引用:https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/#specification)
これと現代の家庭用
ごとに、取り付けることができる最小メモリー容量と最大メモリー容量は決まっています。たとえば、特定の PC 製デスクトップまたはノートパソコンは、最小 Dell 2 、最大 GB 16 のメモリーをサポートする場合があります。 GB
2GB
らしい。192KB
と比較してみよう。
> let wio = 192;
< 192
> let dell = 2 * 1024 * 1024;
< 2097152
> dell / wio
< 10922.666666666666
大凡、一万倍もの格差があるとのこと。
更に128KB
であったという。これは
このように限られた環境下で運用するためには、最低限必要なもの(ここで言う「
検証:フォントを有効にしたことによる影響
実際にフォントを一つ有効にして、その前後を比較してみよう。下は、本記事で後述するカスタムフォント使用時の様子である。
最大507904バイトのフラッシュメモリのうち、スケッチが163288バイト(32%)を使っています。
ここで、LV_FONT_DEJAVU_16_PERSIAN_HEBREW
を有効にするべく、設定を変更する。なお、もともと有効であったフォントは有効のままにしてある。
#ifndef LV_FONT_DEJAVU_16_PERSIAN_HEBREW
// #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, PErisan letters and all their forms*/
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 1 /*Hebrew, Arabic, PErisan letters and all their forms*/
#endif
最大507904バイトのフラッシュメモリのうち、スケッチが202688バイト(39%)を使っています。
単純に差を取ると
より、
39400B
(約38KB
)増えたことが分かる。
若し使わないフォントを有効にしている場合は、念のため無効にすることを推奨する。
カスタムフォントの使い方
続いて、任意のフォントを使う手順について述べる。
ところで、既に「フォントは嵩張る」といった話をした通り、任意のフォントを使う際に容量への配慮を要することは明らかである。後述もするように、「フォントから必要な文字のみ抽出する」という工夫を迫られるだろう。
カスタムフォントの必要性
結論から言えば、(バージョン7.0.2
の場合、)
用意されたフォントは.c
ファイルとして存在しており、その中にはlv_font_simsun_16_cjk.c
というファイルがある。この
このlv_font_simsun_16_cjk.c
を見ると、漢字がフォントのデータとして含まれている。ところが、仮名は全く存在しないのである。
漢文や書簡文、候文で良ければ、「日本語対応可」と言えるだろう。しかし書き下し文は表記できない。なにより、和歌を表現できないではないか。
日本語を扱う上で、用意されたフォントのみでは満足でない。而して、仮名を始め、必要に応じて任意のフォントを用意せねばならぬのである。
フォント入手から適用まで
ここからは、.ttf
ファイルのフォントを
なお、一部手順はこの記事も参考にしている。
1. .ttf
ファイルを入手する
本記事では.ttf
型式のフォントを扱う。なお、手順の確認に重点を置くため、
リンク先の「
画像の右側に「
グリフウィキの1字フォントについて
「
このように汎用的な使途であるため、全ての「
2. .ttf
ファイルの名前を確認する
ダウンロードしたフォントの名前は、
u2ffa-ufa66-u2ff1-u2ff0-u660c-u232ad-u2ff0-u660d-u5dfe.ttf
というものになる。
この名前には次の問題が見て取れる。
- 半角ハイフン
-
が含まれている - 長い
前者は致命的な問題であり、このまま.c
ファイルに変換するとエラーになる。半角アンダーバー_
に置換するか、分かりやすい名前に変えることを忘れてはならない。
後者は、
3. .ttf
ファイルを.c
ファイルに変換する
.ttf
ファイルを.c
ファイルに変換することができる。当然乍ら、
今回は次のように入力項目へ記載した。
項目 | 内容 | 備考 |
---|---|---|
Name |
lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe |
フォントの名前 |
Size |
30 |
単位はピクセル |
Bpp |
8 bit-per-pixel |
標準のフォントの多くは4 bit-per-pixel である |
Fallback |
lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe |
よくわからないのでName と同じにした |
Output format |
C file |
Binary にすることもできる |
チェックボックス | 全部無視 | 拘る人は確り読めばよい |
TTF/WOFF font |
u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.ttf |
ファイルを選択する |
Range |
0x3013 |
〓 の |
Symbols |
〓 |
「〓 に対応する |
これらの内、最後のRange
及びSymbols
は、選択したフォントの中から抽出する文字領域を指定する項目であり、極めて重要な意味を持つ。フォントにより収録する文字数は異なれど、収録される全ての文字を抽出することは現実的でない。
従って、システムで使用する文字を設計時点で洗い出して置き、それらに限定して抽出することが最も望ましい方法である。あるいは、
蛇足:日本語とUnicode
- 記号・句読点
U+3000( )・U+3001(、)・U+3002(。)・U+3005(々)
この他、〆、括弧(〈〉・《》・「」・『』・【】⋯)、などがある
- 平仮名(捨て仮名・濁点付き含む)
U+3041(ぁ) ~ U+3096(ゖ) - 平仮名(濁点・踊り字・合略仮名)
U+3099( ゙) ~ U+309F(ゟ)
※ とU+3099 はダイアクリティカルマークのようになっているため、全角スペースと共に表示している。環境によって表示が崩れる場合があることに注意。U+309A
(崩れそうな表示例:「り゙」「た゚」) - 片仮名(記号・捨て仮名・濁点付き・踊り字・合略仮名含む)
U+30A0(゠) ~ U+30FF(ヿ) - 片仮名拡張
U+31F0(ㇰ) ~ U+31FF(ㇿ) - 囲み
文字・月・CJK 互換用文字CJK
㋿、㌀、㍘、㏡など
- 半角・全角形
半角片仮名(ァ・ィ・ゥ⋯)など
- 変体仮名
U+1B000 ~ U+1B122 - 小書き仮名拡張
変換が終了すると、.c
ファイルがダウンロードされる。
4. .c
ファイルを一部修正する
変換された.c
ファイルの内容を一部修正する。
この手順は「Seeed_Arduino_LvGL
を用いた」が為に生じている可能性があるため、環境によって履行の是非を検討するべきである。
before
/*******************************************************************************
* Size: 30 px
* Bpp: 8
* Opts: --bpp 8 --size 30 --no-compress --font u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.ttf --symbols 〓 --range 12307 --format lvgl -o lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.c
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
︙
};
extern const lv_font_t lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe;
/*-----------------
* PUBLIC FONT
*----------------*/
︙
after
/*******************************************************************************
* Size: 30 px
* Bpp: 8
* Opts: --bpp 8 --size 30 --no-compress --font u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.ttf --symbols 〓 --range 12307 --format lvgl -o lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.c
******************************************************************************/
/*
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
*/
#include <lvgl.h>
︙
};
// extern const lv_font_t lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe;
/*-----------------
* PUBLIC FONT
*----------------*/
︙
#include "lvgl/lvgl.h"
が実行されてエラーが出たため、必ず#include <lvgl.h>
となるようにした。
extern const lv_font_t
は、フォントの宣言云云で触れたマクロLV_FONT_DECLARE
に大きく関与している。
このマクロは、LV_FONT_DECLARE(font_name)
と書いた箇所がextern lv_font_t font_name
と置換されるというものである。今回行う手順では、
LV_FONT_DECLARE(lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe)
として宣言する方法を取るため、これが置換されて
extern lv_font_t lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe
となり、重複する虞がある。よってフォントの.c
ファイル側では、extern const lv_font_t
の記述を削除している。
5. .c
ファイルをフォントのフォルダーに追加する
.c
ファイルが格納されているフォルダーが存在するため、そこに同じくlv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.c
を追加する。
参考:バージョン互換性のなさ
フォルダー名すら変わっている。
-
Seeed_Arduino_LvGL
Seeed_Arduino_LvGL/src/src/lv_font/
-
lvgl
lvgl/src/font/
6. 設定変更
-
lv_font.mk
フォルダーに追加した.c
ファイルの名前を記載する。
before
︙
CSRCS += lv_font_unscii_8.c
CSRCS += lv_font_dejavu_16_persian_hebrew.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_font
︙
after
︙
CSRCS += lv_font_unscii_8.c
CSRCS += lv_font_dejavu_16_persian_hebrew.c
# custom font
# CSRCS += lv_font_glyphwiki_u3771_var_002.c # 別のカスタムフォントを試した跡
CSRCS += lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_font
︙
-
lv_font.h
LV_FONT_DECLARE
マクロでフォントを宣言し、有効にする。
before
︙
/*Declare the custom (user defined) fonts*/
#ifdef LV_FONT_CUSTOM_DECLARE
LV_FONT_CUSTOM_DECLARE
#endif
︙
after
︙
/*Declare the custom (user defined) fonts*/
#ifdef LV_FONT_CUSTOM_DECLARE
// LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(lv_font_glyphwiki_u3771_var_002) // 別のカスタムフォントを試した跡
LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe)
#endif
︙
以上の手順で、カスタムフォントを導入することができた。
カスタムフォント実装例
導入したフォントが正しく機能するか、実際にアプリケーションを作って動作確認する。本記事のプログラムはあくまでも
プログラム
- 抽象部
#ifndef __LVGL_ARDUINO_ABSTRACT_LAYER_HPP__
#define __LVGL_ARDUINO_ABSTRACT_LAYER_HPP__
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <lvgl.h>
template<class T>
class LAAL {
private:
/* delete copy constructor */
LAAL(const LAAL&) = delete;
/* delete copy operator */
LAAL& operator=(const LAAL&) = delete;
protected:
/* singleton */
static T* __smpLaalSingleton;
/* TFT LCD */
static TFT_eSPI* __mpTft;
/* tick (1~10) */
uint32_t __mu32TickPeriod;
/* ディスプレイ */
/* display buffer */
lv_disp_buf_t __smDisplayBuffer;
/* main color buffer */
lv_color_t __smColorBufferMain[LV_HOR_RES_MAX * 10];
/* sub color buffer */
lv_color_t __smColorBufferSub[LV_HOR_RES_MAX * 10];
/* display driver */
lv_disp_drv_t __mDisplayDriver;
/* display */
lv_disp_t* __mpDisplay;
/* 画面初期化 */
static void __mFDisplayFlush(
lv_disp_drv_t* pDisplayDriver,
const lv_area_t* pArea,
lv_color_t* pColor
);
/* 画面設定 */
virtual void __mFDisplaySetup();
/* 入力デバイス(encode) */
/* input device driver */
lv_indev_drv_t __mInputDeviceDriverEncoder;
/* input device */
lv_indev_t* __mpInputDeviceEncoder;
/* Reading encoder callback */
static bool __mFbReadEncoder(
lv_indev_drv_t* pInputDeviceDriver,
lv_indev_data_t* pInputDevicesData
);
/* デバイス設定 */
virtual void __mFDeviceSetup();
/* 画面要素 */
/* widget */
/*
example:
lv_obj_t* __mpObject;
void __mFObjectEventhandler(
lv_obj_t* pObject,
lv_event_t event
) = 0;
*/
/* group */
/*
example:
lv_group_t* __mpGroup;
void __mFGroupSetup();
*/
/* 画面構成 */
virtual void __mFContentsSetup() = 0;
/* constructor */
void __mFNew();
LAAL() = default;
/* destructor */
virtual ~LAAL() = default;
public:
/* 設定 */
void mFSetup();
/* 画面実行 */
void mFOperateGraphic();
};
#include "LvglArduinoAbstractLayer.ipp"
#endif // __LVGL_ARDUINO_ABSTRACT_LAYER_HPP__
template<class T>
T* LAAL<T>::__smpLaalSingleton = nullptr;
template<class T>
TFT_eSPI* LAAL<T>::__mpTft = nullptr;
template<class T>
void LAAL<T>::__mFNew() {
/* lvglの初期化 */
lv_init();
/* TFTの初期設定 */
(this -> __mpTft) -> begin();
(this -> __mpTft) -> setRotation(3);
}
template<class T>
void LAAL<T>::mFSetup() {
/* 画面設定 */
(this -> __mFDisplaySetup)();
/* 入力設定 */
(this -> __mFDeviceSetup)();
/* 画面作成 */
(this -> __mFContentsSetup)();
}
template<class T>
void LAAL<T>::__mFDisplayFlush(
lv_disp_drv_t* pDisplayDriver,
const lv_area_t* pArea,
lv_color_t* pColor
) {
const uint32_t w = pArea -> x2 - pArea -> x1 + 1;
const uint32_t h = pArea -> y2 - pArea -> y1 + 1;
LAAL<T>::__mpTft -> startWrite();
LAAL<T>::__mpTft -> setAddrWindow(pArea -> x1, pArea -> y1, w, h);
LAAL<T>::__mpTft -> pushColors(&pColor -> full, w * h, true);
LAAL<T>::__mpTft -> endWrite();
lv_disp_flush_ready(pDisplayDriver);
}
template<class T>
void LAAL<T>::mFOperateGraphic() {
while (1) {
/* operate tasks */
this -> __mu32TickPeriod = lv_task_handler();
/* delay */
delay(this -> __mu32TickPeriod);
/* tell lvgl system elapsed time */
lv_tick_inc(this -> __mu32TickPeriod);
}
}
template<class T>
void LAAL<T>::__mFDisplaySetup() {
/* 画面表示用bufferそのものの初期化 */
lv_disp_buf_init(
&(this -> __smDisplayBuffer),
this -> __smColorBufferMain,
this -> __smColorBufferSub,
LV_HOR_RES_MAX * 10
);
/* 画面制御設定 */
lv_disp_drv_init(&(this -> __mDisplayDriver));
(this -> __mDisplayDriver).ver_res = LV_VER_RES_MAX;
(this -> __mDisplayDriver).flush_cb = this -> __mFDisplayFlush;
(this -> __mDisplayDriver).buffer = &(this -> __smDisplayBuffer);
this -> __mpDisplay = lv_disp_drv_register(&(this -> __mDisplayDriver));
}
template<class T>
bool LAAL<T>::__mFbReadEncoder(
lv_indev_drv_t* pInputDeviceDriver,
lv_indev_data_t* pInputDevicesData
) {
(void) pInputDeviceDriver;
(void) pInputDevicesData;
return false;
}
template<class T>
void LAAL<T>::__mFDeviceSetup() {
/* 入力の設定 */
lv_indev_drv_init(&(this -> __mInputDeviceDriverEncoder));
(this -> __mInputDeviceDriverEncoder).type = LV_INDEV_TYPE_ENCODER;
(this -> __mInputDeviceDriverEncoder).read_cb = this -> __mFbReadEncoder;
this -> __mpInputDeviceEncoder = lv_indev_drv_register(&(this -> __mInputDeviceDriverEncoder));
}
- アプリケーション部
#ifndef __SIMPLE_FONT_PLAY_GROUND_HPP__
#define __SIMPLE_FONT_PLAY_GROUND_HPP__
#include "LvglArduinoAbstractLayer.hpp"
class App final: public LAAL<App> {
private:
/* 画面設定 */
void __mFDisplaySetup();
// /* last tick */
// static uint32_t __mu32LastTick;
/* Reading encoder callback */
static bool __mFbReadEncoder(
lv_indev_drv_t* pInputDeviceDriver,
lv_indev_data_t* pInputDevicesData
);
/* デバイス設定 */
void __mFDeviceSetup();
/* position */
/* array */
const lv_point_t __maPosition[3] = {{0,0}, {0, 1}, {1,1}};
/* tileview */
static lv_obj_t* __mpObjectTileview;
/* tile */
static lv_obj_t* __mpObjectTile;
/* label */
static lv_obj_t* __mpObjectLabel;
/* tileview配置 */
void __mFTileviewSetup();
// /* group */
// static lv_group_t* __mpGroup;
// /* group設定 */
// void __mFGroupSetup();
/* 画面構成 */
void __mFContentsSetup();
/* constructor */
App();
/* destructor */
~App();
public:
/* 初期化 */
static App* mFpLaalInitialize(
TFT_eSPI* pTft
);
};
#endif // __SIMPLE_FONT_PLAY_GROUND_HPP__
#include "SimpleFontPlayGround.hpp"
/* static member variable */
// uint32_t App::__mu32LastTick = 0;
lv_obj_t* App::__mpObjectTileview = nullptr;
lv_obj_t* App::__mpObjectTile = nullptr;
lv_obj_t* App::__mpObjectLabel = nullptr;
// lv_group_t* App::__mpGroup = nullptr;
/* member function */
/* initialize */
/*static*/ App* App::mFpLaalInitialize(
TFT_eSPI* pTft
) {
/* 未定ならば初期化 */
if (LAAL<App>::__smpLaalSingleton == nullptr) {
/* static member variableの初期化 */
LAAL<App>::__mpTft = pTft;
/* 子クラスの初期化 */
LAAL<App>::__smpLaalSingleton = new App();
}
/* 既初期化の場合でも既存インスタンスへのポインターが返却される */
return LAAL<App>::__smpLaalSingleton;
}
App::App() {
LAAL<App>::__mFNew();
}
App::~App() {}
/* display */
void App::__mFDisplaySetup() {
LAAL<App>::__mFDisplaySetup();
}
/* input */
/*static*/ bool App::__mFbReadEncoder(
lv_indev_drv_t* pInputDeviceDriver,
lv_indev_data_t* pInputDevicesData
) {
(void) pInputDeviceDriver;
(void) pInputDevicesData;
// /* 経過時間 */
// uint32_t u32TickElapsed = lv_tick_get() - App::__mu32LastTick;
// /* tick更新 */
// bool bUpdateTick = false;
// /* 押下如何 */
// if (digitalRead(WIO_5S_PRESS) == LOW) {
// /* send pressed */
// lv_group_send_data(App::__mpGroup, LV_KEY_ENTER);
// /* set state pressed */
// pInputDevicesData -> state = LV_INDEV_STATE_PR;
// /* update */
// bUpdateTick = true;
// }
// else {
// /* set state relesed */
// pInputDevicesData -> state = LV_INDEV_STATE_REL;
// }
// /* 左 */
// if (digitalRead(WIO_5S_LEFT) == LOW && u32TickElapsed > 250) {
// /* send left */
// lv_group_send_data(App::__mpGroup, LV_KEY_LEFT);
// /* update */
// bUpdateTick = true;
// }
// /* 右 */
// else if (digitalRead(WIO_5S_RIGHT) == LOW && u32TickElapsed > 250) {
// /* send right */
// lv_group_send_data(App::__mpGroup, LV_KEY_RIGHT);
// /* update */
// bUpdateTick = true;
// }
// /* 上 */
// if (digitalRead(WIO_5S_UP) == LOW && u32TickElapsed > 250) {
// /* send up */
// lv_group_send_data(App::__mpGroup, LV_KEY_UP);
// /* update */
// bUpdateTick = true;
// }
// /* 下 */
// else if (digitalRead(WIO_5S_DOWN) == LOW && u32TickElapsed > 250) {
// /* send down */
// lv_group_send_data(App::__mpGroup, LV_KEY_DOWN);
// /* update */
// bUpdateTick = true;
// }
// /* B (中) */
// if (digitalRead(WIO_KEY_B) == LOW && u32TickElapsed > 250) {
// /* focus to */
// lv_group_focus_obj(App::__);
// /* update */
// bUpdateTick = true;
// }
// /* A (右) */
// if (digitalRead(WIO_KEY_A) == LOW && u32TickElapsed > 250) {
// /* positive difference (focus) */
// pInputDevicesData -> enc_diff = 1;
// /* update */
// bUpdateTick = true;
// }
// /* C (左) */
// else if (digitalRead(WIO_KEY_C) == LOW && u32TickElapsed > 250) {
// /* negative difference (focus) */
// pInputDevicesData -> enc_diff = -1;
// /* update */
// bUpdateTick = true;
// }
// else {
// /* zero defference */
// pInputDevicesData -> enc_diff = 0;
// }
// if (bUpdateTick) {
// /* update tick */
// App::__mu32LastTick = lv_tick_get();
// }
/* no data buffered */
return false;
}
void App::__mFDeviceSetup() {
/* 入力の設定 */
lv_indev_drv_init(&(LAAL<App>::__mInputDeviceDriverEncoder));
(LAAL<App>::__mInputDeviceDriverEncoder).type = LV_INDEV_TYPE_ENCODER;
(LAAL<App>::__mInputDeviceDriverEncoder).read_cb = App::__mFbReadEncoder;
LAAL<App>::__mpInputDeviceEncoder = lv_indev_drv_register(&(LAAL<App>::__mInputDeviceDriverEncoder));
// /* enable 5way switch */
// pinMode(WIO_5S_UP, INPUT);
// pinMode(WIO_5S_DOWN, INPUT);
// pinMode(WIO_5S_LEFT, INPUT);
// pinMode(WIO_5S_RIGHT, INPUT);
// pinMode(WIO_5S_PRESS, INPUT);
// /* enable 3 buttons */
// pinMode(WIO_KEY_A, INPUT);
// pinMode(WIO_KEY_B, INPUT);
// pinMode(WIO_KEY_C, INPUT);
}
/* contents */
void App::__mFContentsSetup() {
(this -> __mFTileviewSetup)();
// (this -> __mFGroupSetup)();
}
/* callback */
/* widget */
void App::__mFTileviewSetup() {
/* create a tileview */
this -> __mpObjectTileview = lv_tileview_create(lv_scr_act(), NULL);
/* set valid positions */
lv_tileview_set_valid_positions(this -> __mpObjectTileview, this -> __maPosition, 3);
/* set edge flash */
lv_tileview_set_edge_flash(this -> __mpObjectTileview, true);
/* create a tile */
this -> __mpObjectTile = lv_obj_create(this -> __mpObjectTileview, NULL);
/* set size */
lv_obj_set_size(this -> __mpObjectTile, LV_HOR_RES, LV_VER_RES);
/* add this tile to the tileview */
lv_tileview_add_element(this -> __mpObjectTileview, this -> __mpObjectTile);
/* create a label */
this -> __mpObjectLabel = lv_label_create(this -> __mpObjectTile, NULL);
/* set the label center of the tile */
lv_obj_align(this -> __mpObjectLabel, NULL, LV_ALIGN_CENTER, 0, 0);
/* set text */
// lv_label_set_text(this -> __mpObjectLabel, "A");
// lv_label_set_text(this -> __mpObjectLabel, "ת");
lv_label_set_text(this -> __mpObjectLabel, "〓");
/* set text font */
lv_obj_set_style_local_text_font(
this -> __mpObjectLabel,
LV_LABEL_PART_MAIN,
LV_STATE_DEFAULT,
&lv_font_glyphwiki_u2ffa_ufa66_u2ff1_u2ff0_u660c_u232ad_u2ff0_u660d_u5dfe
// &lv_font_dejavu_16_persian_hebrew
);
}
/* group */
// void App::__mFGroupSetup() {
// /* create group */
// this -> __mpGroup = lv_group_create();
// /* set the input device to the group */
// lv_indev_set_group(LAAL<App>::__mpInputDeviceEncoder, this -> __mpGroup);
// /* add the objects to the group */
// /* focus to tileview */
// }
-
.ino
ファイル
#include <TFT_eSPI.h>
#include <lvgl.h>
#include "SimpleFontPlayGround.hpp"
/* TFT LCD */
static TFT_eSPI TFT;
/* App */
App* pApp;
void setup() {
pApp = App::mFpLaalInitialize(&TFT);
pApp -> mFSetup();
}
void loop() {
pApp -> mFOperateGraphic();
}
実行結果
文字の小ささと複雑さが相俟ってはっきり見えないが、文字コードの存在しない文字を画面に表示させることができている。このことから、フォントが正しく導入され、機能していることが確かめられる。
跋
本記事では簡単な例に留めたため、より実践的な場面ではこの通り進まず彳亍することもあるだろう。目下の課題は、仮名を表示させることとなる。
Discussion