-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathkfont.hpp
258 lines (227 loc) · 6.53 KB
/
kfont.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#pragma once
//=====================================================================//
/*! @file
@brief 漢字フォント・クラス
@author 平松邦仁 ([email protected])
@copyright Copyright (C) 2018 Kunihito Hiramatsu @n
Released under the MIT license @n
https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "ff14/source/ff.h"
#include "common/vtx.hpp"
// 漢字フォントデータをSDカード上に置いて、キャッシュアクセスする場合有効にする
// #define CASH_KFONT
#ifdef CASH_KFONT
extern "C" {
int fatfs_get_mount();
};
#endif
namespace graphics {
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief 漢字無効フォント定義 @n
※漢字フォントを使わない場合の定義として
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
class kfont_null {
public:
static constexpr int8_t width = 0;
static constexpr int8_t height = 0;
void flush_cash() noexcept { }
const uint8_t* get(uint16_t code) noexcept { return nullptr; }
bool injection_utf8(uint8_t ch) noexcept { return true; }
uint16_t get_utf16() const noexcept { return 0x0000; }
};
#ifndef CASH_KFONT
struct kfont_bitmap {
static const uint8_t kfont_start[];
};
#endif
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief 漢字フォント・テンプレート・クラス
@param[in] WIDTH フォントの横幅
@param[in] HEIGHT フォントの高さ
@param[in] CASHN キャッシュ数
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
#ifdef CASH_KFONT
template <int8_t WIDTH, int8_t HEIGHT, uint8_t CASHN>
#else
template <int8_t WIDTH, int8_t HEIGHT>
#endif
class kfont {
static constexpr uint32_t FONTS = ((WIDTH * HEIGHT) + 7) / 8;
uint16_t code_;
int8_t cnt_;
#ifdef CASH_KFONT
struct kanji_cash {
uint16_t code;
uint8_t bitmap[FONTS];
kanji_cash() noexcept : code(0), bitmap{ 0 } { }
};
kanji_cash cash_[CASHN];
uint8_t cash_idx_;
#endif
static uint16_t sjis_to_liner_(uint16_t sjis)
{
uint16_t code;
uint8_t up = sjis >> 8;
uint8_t lo = sjis & 0xff;
if(0x81 <= up && up <= 0x9f) {
code = up - 0x81;
} else if(0xe0 <= up && up <= 0xef) {
code = (0x9f + 1 - 0x81) + up - 0xe0;
} else {
return 0xffff;
}
uint16_t loa = (0x7e + 1 - 0x40) + (0xfc + 1 - 0x80);
if(0x40 <= lo && lo <= 0x7e) {
code *= loa;
code += lo - 0x40;
} else if(0x80 <= lo && lo <= 0xfc) {
code *= loa;
code += 0x7e + 1 - 0x40;
code += lo - 0x80;
} else {
return 0xffff;
}
return code;
}
public:
//-----------------------------------------------------------------//
/*!
@brief コンストラクター
*/
//-----------------------------------------------------------------//
kfont() noexcept : code_(0), cnt_(0)
#ifdef CASH_KFONT
, cash_(), cash_idx_(0)
#endif
{ }
//-----------------------------------------------------------------//
/*!
@brief 文字の横幅
*/
//-----------------------------------------------------------------//
static constexpr int8_t width = WIDTH;
//-----------------------------------------------------------------//
/*!
@brief 文字の高さ
*/
//-----------------------------------------------------------------//
static constexpr int8_t height = HEIGHT;
//-----------------------------------------------------------------//
/*!
@brief キャッシュのフラッシュ
*/
//-----------------------------------------------------------------//
void flush_cash() noexcept
{
#ifdef CASH_KFONT
for(uint8_t i = 0; i < CASHN; ++i) {
cash_[i].code = 0;
}
cash_idx_ = 0;
#endif
}
//-----------------------------------------------------------------//
/*!
@brief 文字のビットマップを取得
@param[in] code 文字コード(unicode)
@return 文字のビットマップ
*/
//-----------------------------------------------------------------//
const uint8_t* get(uint16_t code) noexcept {
if(code == 0) return nullptr;
#ifdef CASH_KFONT
// キャッシュ内検索
int8_t n = -1;
for(uint8_t i = 0; i < CASHN; ++i) {
if(cash_[i].code == code) {
return &cash_[i].bitmap[0];
} else if(cash_[i].code == 0) {
n = i;
}
}
if(n >= 0) cash_idx_ = n;
else {
for(uint8_t i = 0; i < CASHN; ++i) {
++cash_idx_;
if(cash_idx_ >= CASHN) cash_idx_ = 0;
if(cash_[cash_idx_].code != 0) {
break;
}
}
}
if(fatfs_get_mount() == 0) return nullptr;
#endif
uint32_t lin = sjis_to_liner_(ff_uni2oem(code, FF_CODE_PAGE));
if(lin == 0xffff) {
return nullptr;
}
#ifdef CASH_KFONT
FIL fp;
if(f_open(&fp, "/kfont16.bin", FA_READ) != FR_OK) {
return nullptr;
}
if(f_lseek(&fp, lin * FONTS) != FR_OK) {
f_close(&fp);
return nullptr;
}
UINT rs;
if(f_read(&fp, &cash_[cash_idx_].bitmap[0], FONTS, &rs) != FR_OK) {
f_close(&fp);
return nullptr;
}
cash_[cash_idx_].code = code;
f_close(&fp);
return &cash_[cash_idx_].bitmap[0];
#else
return &kfont_bitmap::kfont_start[lin * FONTS];
#endif
}
//-----------------------------------------------------------------//
/*!
@brief UTF-8 コードを押し込む
@return UTF-16 コードが完了した場合「true」
*/
//-----------------------------------------------------------------//
bool injection_utf8(uint8_t ch) noexcept
{
if(ch < 0x80) {
code_ = ch;
return true;
} else if((ch & 0xf0) == 0xe0) {
code_ = (ch & 0x0f);
cnt_ = 2;
return false;
} else if((ch & 0xe0) == 0xc0) {
code_ = (ch & 0x1f);
cnt_ = 1;
return false;
} else if((ch & 0xc0) == 0x80) {
code_ <<= 6;
code_ |= ch & 0x3f;
cnt_--;
if(cnt_ <= 0 && code_ < 0x80) {
code_ = 0; // 不正なコードとして無視
return true;
}
}
if(cnt_ == 0 && code_ != 0) {
return true;
}
return false;
}
//-----------------------------------------------------------------//
/*!
@brief UTF-16 コードを取得
@return UTF-16 コード
*/
//-----------------------------------------------------------------//
uint16_t get_utf16() const noexcept { return code_; }
};
}