前回は、フレームバッファを引き継いでカーネルから画面描画することを学びました。
今回は、テキストを画面上に描画するための処理を勉強していくことになるみたいです。
画面上に '文字' を表示するためにはフォントデータが必要になる(計算の都合上、2 のべき乗で表されるサイズだと都合がとてもいい)。
多分、フォントデータの種類にはいくつかあるのだと思うけれども、いわゆるビットマップフォントで実装が進む模様。
// "A" を表すフォントデータ
const uint8_t kFontA[16] = {
0b00000000, //
0b00011000, // **
0b00011000, // **
0b00011000, // **
0b00011000, // **
0b00100100, // * *
0b00100100, // * *
0b00100100, // * *
0b00100100, // * *
0b01111110, // ******
0b01000010, // * *
0b01000010, // * *
0b01000010, // * *
0b11100111, // *** ***
0b00000000, //
0b00000000, //
};
そして、フォントデータ上の任意の座標位置のビット状態を判断して、描画するか/否かを判断するロジックはこんな感じ。 1 ビットずつ左にシフトしていって、0×80(=0b10000000)と AND 演算した結果が真であればそのドットは描画対象になる。
dx | 0xC1 << dx | (0xC1 << dx) & 0xC1 | 結果 |
---|---|---|---|
0 | 0b 00000000 11000001 | 0b 00000000 1 10000010b 00000000 1 0000000 | TRUE |
1 | 0b 00000001 10000010 | 0b 00000001 1 00000100b 00000000 1 0000000 | TRUE |
2 | 0b 00000011 00000100 | 0b 00000011 0 00001000b 00000000 1 0000000 | FALSE |
3 | 0b 00000110 00001000 | 0b 00000110 0 00010000b 00000000 1 0000000 | FALSE |
4 | 0b 00001100 00010000 | 0b 00001100 0 00100000b 00000000 1 0000000 | FALSE |
5 | 0b 00011000 00100000 | 0b 00011000 0 01000000b 00000000 1 0000000 | FALSE |
6 | 0b 01100000 01000000 | 0b 01100000 0 10000000b 00000000 1 0000000 | FALSE |
7 | 0b 11000000 10000000 | 0b 11000000 1 00000000b 00000000 1 0000000 | TRUE |
あとは、フォントを描画する関数を定義&呼び出してあげれば良い。
void WriteAscii(PixelWriter& writer, int x, int y, char c, const PixelColor& color) {
if (c != 'A') {
return;
}
for (int dy = 0; dy < 16; ++dy) {
for (int dx = 0; dx < 8; ++dx) {
if ((kFontA[dy] << dx) & 0x80u) {
writer.Write(x + dx, y + dy, color);
}
}
}
}
extern "C" void KernelMain(const FrameBufferConfig& frame_buffer_config) {
// :
WriteAscii(*pixel_writer, 50, 50, 'A', {0, 0, 0});
WriteAscii(*pixel_writer, 58, 50, 'A', {0, 0, 0});
// :
}
おおーー! でけた!
(まだ続く…)