16
17
18
19
20
21template <
typename RGB_T =
RGB565>
25 using Glyph = std::array<uint8_t, 7>;
27 using CodePoint = uint32_t;
42 const Glyph&
glyph(
char character)
const {
43 return glyph(
static_cast<CodePoint>(
static_cast<
unsigned char>(character)));
47 const Glyph&
glyph(CodePoint codePoint)
const {
48 if (codePoint >=
static_cast<
unsigned char>(
kFirstChar) &&
49 codePoint <=
static_cast<
unsigned char>(
kLastChar)) {
50 return glyphTable()[glyphIndex(codePoint)];
53 const Glyph* mappedGlyph = glyphForExtendedCodePoint(codePoint);
54 return mappedGlyph !=
nullptr ? *mappedGlyph : replacementGlyph();
58 bool pixel(
char character, uint8_t x, uint8_t y)
const {
59 return pixel(
static_cast<CodePoint>(
static_cast<
unsigned char>(character)),
64 bool pixel(CodePoint codePoint, uint8_t x, uint8_t y)
const {
69 const uint8_t rowMask = glyph(codePoint)[y];
70 return (rowMask &
static_cast<uint8_t>(1U << (
kGlyphWidth - 1 - x))) != 0;
74 void drawChar(ISurface<RGB_T>& target, int16_t x, int16_t y,
char character,
75 RGB_T foreground, RGB_T background = RGB_T(0),
76 bool opaque =
false, uint8_t scale = 1)
const {
78 static_cast<CodePoint>(
static_cast<
unsigned char>(character))
,
79 foreground
, background
, opaque
, scale
);
84 CodePoint codePoint, RGB_T foreground,
85 RGB_T background = RGB_T(0),
bool opaque =
false,
86 uint8_t scale = 1)
const {
92 for (uint8_t column = 0; column <
kGlyphWidth; ++column) {
93 const int16_t pixelX =
static_cast<int16_t>(x + (column * scale));
94 const int16_t pixelY =
static_cast<int16_t>(y + (row * scale));
96 if (pixel(codePoint, column, row)) {
97 target.fillRect(pixelX, pixelY, scale, scale, foreground);
99 target.fillRect(pixelX, pixelY, scale, scale, background);
106 void drawText(ISurface<RGB_T>& target, int16_t x, int16_t y,
const char* text,
107 RGB_T foreground, RGB_T background = RGB_T(0),
108 bool opaque =
false, uint8_t scale = 1, uint8_t spacing = 1,
109 uint8_t lineSpacing = 1)
const override {
110 if (text ==
nullptr) {
117 const int16_t advanceX =
118 static_cast<int16_t>((
kGlyphWidth * scale) + spacing);
119 const int16_t advanceY =
120 static_cast<int16_t>((
kGlyphHeight * scale) + lineSpacing);
124 const char* current = text;
125 while (*current !=
'\0') {
126 if (*current ==
'\n') {
129 cursorY =
static_cast<int16_t>(cursorY + advanceY);
133 const CodePoint codePoint = decodeNextUtf8(current);
136 cursorX =
static_cast<int16_t>(cursorX + advanceX);
143 if (text ==
nullptr || *text ==
'\0') {
150 size_t lineLength = 0;
151 size_t longestLine = 0;
152 const char* current = text;
153 while (*current !=
'\0') {
154 if (*current ==
'\n') {
156 if (lineLength > longestLine) {
157 longestLine = lineLength;
161 decodeNextUtf8(current);
166 if (lineLength > longestLine) {
167 longestLine = lineLength;
170 if (longestLine == 0) {
174 return (longestLine * kGlyphWidth * scale) + ((longestLine - 1) * spacing);
180 if (text ==
nullptr || *text ==
'\0') {
188 for (
const char* current = text; *current !=
'\0'; ++current) {
189 if (*current ==
'\n') {
194 return (lines * kGlyphHeight * scale) + ((lines - 1) * lineSpacing);
203 size_t glyphIndex(CodePoint codePoint)
const {
204 if (codePoint <
static_cast<
unsigned char>(
kFirstChar) ||
205 codePoint >
static_cast<
unsigned char>(
kLastChar)) {
208 return codePoint -
static_cast<
unsigned char>(
kFirstChar);
211 const Glyph& replacementGlyph()
const {
212 return glyphTable()[glyphIndex(
static_cast<CodePoint>(
'?'))];
215 const Glyph& asciiGlyph(
char character)
const {
216 return glyphTable()[glyphIndex(
217 static_cast<CodePoint>(
static_cast<
unsigned char>(character)))];
220 const Glyph* asciiGlyphPtr(
char character)
const {
221 return &asciiGlyph(character);
224 const Glyph* glyphForExtendedCodePoint(CodePoint codePoint)
const {
231 return asciiGlyphPtr(
',');
234 return asciiGlyphPtr(
'f');
237 return asciiGlyphPtr(
'"');
240 return asciiGlyphPtr(
'.');
245 return asciiGlyphPtr(
'+');
248 return asciiGlyphPtr(
'^');
251 return asciiGlyphPtr(
'%');
254 return asciiGlyphPtr(
'S');
257 return asciiGlyphPtr(
'<');
260 return asciiGlyphPtr(
'O');
263 return asciiGlyphPtr(
'Z');
268 return asciiGlyphPtr(
'\'');
273 return asciiGlyphPtr(
'"');
276 return bulletGlyphPtr();
281 return asciiGlyphPtr(
'-');
284 return asciiGlyphPtr(
'~');
287 return asciiGlyphPtr(
'T');
290 return asciiGlyphPtr(
's');
293 return asciiGlyphPtr(
'>');
296 return asciiGlyphPtr(
'o');
299 return asciiGlyphPtr(
'z');
302 return asciiGlyphPtr(
'Y');
304 return asciiGlyphPtr(
' ');
306 return asciiGlyphPtr(
'!');
310 return &sterlingGlyph();
312 return asciiGlyphPtr(
'$');
316 return asciiGlyphPtr(
'|');
318 return §ionGlyph();
320 return asciiGlyphPtr(
'"');
322 return ©rightGlyph();
324 return asciiGlyphPtr(
'a');
326 return asciiGlyphPtr(
'<');
330 return asciiGlyphPtr(
'-');
332 return asciiGlyphPtr(
'R');
334 return asciiGlyphPtr(
'-');
336 return °reeGlyph();
338 return &plusMinusGlyph();
340 return asciiGlyphPtr(
'2');
342 return asciiGlyphPtr(
'3');
344 return asciiGlyphPtr(
'\'');
346 return µGlyph();
348 return ¶graphGlyph();
350 return bulletGlyphPtr();
352 return asciiGlyphPtr(
',');
354 return asciiGlyphPtr(
'1');
356 return asciiGlyphPtr(
'o');
358 return asciiGlyphPtr(
'>');
362 return asciiGlyphPtr(
'/');
364 return asciiGlyphPtr(
'?');
372 return asciiGlyphPtr(
'A');
374 return asciiGlyphPtr(
'C');
379 return asciiGlyphPtr(
'E');
384 return asciiGlyphPtr(
'I');
386 return asciiGlyphPtr(
'D');
388 return asciiGlyphPtr(
'N');
395 return asciiGlyphPtr(
'O');
397 return &multiplyGlyph();
402 return asciiGlyphPtr(
'U');
404 return asciiGlyphPtr(
'Y');
406 return asciiGlyphPtr(
'P');
408 return asciiGlyphPtr(
'B');
416 return asciiGlyphPtr(
'a');
418 return asciiGlyphPtr(
'c');
423 return asciiGlyphPtr(
'e');
428 return asciiGlyphPtr(
'i');
430 return asciiGlyphPtr(
'd');
432 return asciiGlyphPtr(
'n');
439 return asciiGlyphPtr(
'o');
441 return ÷Glyph();
446 return asciiGlyphPtr(
'u');
449 return asciiGlyphPtr(
'y');
451 return asciiGlyphPtr(
'p');
457 const Glyph* bulletGlyphPtr()
const {
458 static const Glyph glyph = {0b00000, 0b00100, 0b01110, 0b01110,
459 0b01110, 0b00100, 0b00000};
463 const Glyph& euroGlyph()
const {
464 static const Glyph glyph = {0b00110, 0b01001, 0b11100, 0b11110,
465 0b11100, 0b01001, 0b00110};
469 const Glyph& centGlyph()
const {
470 static const Glyph glyph = {0b00100, 0b01110, 0b10100, 0b10000,
471 0b10100, 0b01110, 0b00100};
475 const Glyph& sterlingGlyph()
const {
476 static const Glyph glyph = {0b00110, 0b01001, 0b01000, 0b11100,
477 0b01000, 0b11111, 0b01000};
481 const Glyph& yenGlyph()
const {
482 static const Glyph glyph = {0b10001, 0b01010, 0b11111, 0b00100,
483 0b11111, 0b00100, 0b00100};
487 const Glyph& sectionGlyph()
const {
488 static const Glyph glyph = {0b01110, 0b10000, 0b01100, 0b00010,
489 0b00110, 0b00001, 0b11110};
493 const Glyph& copyrightGlyph()
const {
494 static const Glyph glyph = {0b01110, 0b10001, 0b10111, 0b10101,
495 0b10111, 0b10001, 0b01110};
499 const Glyph& notGlyph()
const {
500 static const Glyph glyph = {0b00000, 0b00000, 0b11111, 0b00001,
501 0b00001, 0b00000, 0b00000};
505 const Glyph& degreeGlyph()
const {
506 static const Glyph glyph = {0b00110, 0b01001, 0b01001, 0b00110,
507 0b00000, 0b00000, 0b00000};
511 const Glyph& plusMinusGlyph()
const {
512 static const Glyph glyph = {0b00000, 0b00100, 0b00100, 0b11111,
513 0b00100, 0b11111, 0b00000};
517 const Glyph& microGlyph()
const {
518 static const Glyph glyph = {0b10001, 0b10001, 0b10001, 0b10011,
519 0b01101, 0b10000, 0b10000};
523 const Glyph& paragraphGlyph()
const {
524 static const Glyph glyph = {0b11110, 0b10110, 0b10110, 0b11110,
525 0b00100, 0b00100, 0b00100};
529 const Glyph& multiplyGlyph()
const {
530 static const Glyph glyph = {0b00000, 0b10001, 0b01010, 0b00100,
531 0b01010, 0b10001, 0b00000};
535 const Glyph& divideGlyph()
const {
536 static const Glyph glyph = {0b00000, 0b00100, 0b00000, 0b11111,
537 0b00000, 0b00100, 0b00000};
541 CodePoint decodeNextUtf8(
const char*& current)
const {
542 const unsigned char firstByte =
static_cast<
unsigned char>(*current);
543 if (firstByte == 0) {
547 if ((firstByte & 0x80U) == 0) {
549 return static_cast<CodePoint>(firstByte);
552 uint8_t sequenceLength = 0;
553 CodePoint codePoint = 0;
554 if ((firstByte & 0xE0U) == 0xC0U) {
556 codePoint =
static_cast<CodePoint>(firstByte & 0x1FU);
557 }
else if ((firstByte & 0xF0U) == 0xE0U) {
559 codePoint =
static_cast<CodePoint>(firstByte & 0x0FU);
560 }
else if ((firstByte & 0xF8U) == 0xF0U) {
562 codePoint =
static_cast<CodePoint>(firstByte & 0x07U);
565 return static_cast<CodePoint>(
'?');
568 for (uint8_t index = 1; index < sequenceLength; ++index) {
569 const unsigned char nextByte =
static_cast<
unsigned char>(current[index]);
570 if (nextByte == 0 || (nextByte & 0xC0U) != 0x80U) {
572 return static_cast<CodePoint>(
'?');
575 codePoint =
static_cast<CodePoint>((codePoint << 6) | (nextByte & 0x3FU));
578 current += sequenceLength;
582 const Glyph* glyphTable()
const {
583 static const Glyph kGlyphs[] = {
584 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000,
586 Glyph{0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00000,
588 Glyph{0b01010, 0b01010, 0b01010, 0b00000, 0b00000, 0b00000,
590 Glyph{0b01010, 0b01010, 0b11111, 0b01010, 0b11111, 0b01010,
592 Glyph{0b00100, 0b01111, 0b10100, 0b01110, 0b00101, 0b11110,
594 Glyph{0b11001, 0b11010, 0b00100, 0b01000, 0b10110, 0b00110,
596 Glyph{0b01100, 0b10010, 0b10100, 0b01000, 0b10101, 0b10010,
598 Glyph{0b00100, 0b00100, 0b00100, 0b00000, 0b00000, 0b00000,
600 Glyph{0b00010, 0b00100, 0b01000, 0b01000, 0b01000, 0b00100,
602 Glyph{0b01000, 0b00100, 0b00010, 0b00010, 0b00010, 0b00100,
604 Glyph{0b00000, 0b10101, 0b01110, 0b11111, 0b01110, 0b10101,
606 Glyph{0b00000, 0b00100, 0b00100, 0b11111, 0b00100, 0b00100,
608 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00100, 0b00100,
610 Glyph{0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000,
612 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00100,
614 Glyph{0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b00000,
616 Glyph{0b01110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001,
618 Glyph{0b00100, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100,
620 Glyph{0b01110, 0b10001, 0b00001, 0b00010, 0b00100, 0b01000,
622 Glyph{0b11110, 0b00001, 0b00001, 0b01110, 0b00001, 0b00001,
624 Glyph{0b00010, 0b00110, 0b01010, 0b10010, 0b11111, 0b00010,
626 Glyph{0b11111, 0b10000, 0b11110, 0b00001, 0b00001, 0b10001,
628 Glyph{0b00110, 0b01000, 0b10000, 0b11110, 0b10001, 0b10001,
630 Glyph{0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b01000,
632 Glyph{0b01110, 0b10001, 0b10001, 0b01110, 0b10001, 0b10001,
634 Glyph{0b01110, 0b10001, 0b10001, 0b01111, 0b00001, 0b00010,
636 Glyph{0b00000, 0b00100, 0b00100, 0b00000, 0b00100, 0b00100,
638 Glyph{0b00000, 0b00100, 0b00100, 0b00000, 0b00100, 0b00100,
640 Glyph{0b00010, 0b00100, 0b01000, 0b10000, 0b01000, 0b00100,
642 Glyph{0b00000, 0b00000, 0b11111, 0b00000, 0b11111, 0b00000,
644 Glyph{0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100,
646 Glyph{0b01110, 0b10001, 0b00001, 0b00010, 0b00100, 0b00000,
648 Glyph{0b01110, 0b10001, 0b00001, 0b01101, 0b10101, 0b10101,
650 Glyph{0b01110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001,
652 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001,
654 Glyph{0b01110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001,
656 Glyph{0b11100, 0b10010, 0b10001, 0b10001, 0b10001, 0b10010,
658 Glyph{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000,
660 Glyph{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000,
662 Glyph{0b01110, 0b10001, 0b10000, 0b10111, 0b10001, 0b10001,
664 Glyph{0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001,
666 Glyph{0b01110, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
668 Glyph{0b00001, 0b00001, 0b00001, 0b00001, 0b10001, 0b10001,
670 Glyph{0b10001, 0b10010, 0b10100, 0b11000, 0b10100, 0b10010,
672 Glyph{0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000,
674 Glyph{0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001,
676 Glyph{0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001,
678 Glyph{0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001,
680 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000,
682 Glyph{0b01110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10010,
684 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10100, 0b10010,
686 Glyph{0b01111, 0b10000, 0b10000, 0b01110, 0b00001, 0b00001,
688 Glyph{0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
690 Glyph{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001,
692 Glyph{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01010,
694 Glyph{0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b10101,
696 Glyph{0b10001, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001,
698 Glyph{0b10001, 0b10001, 0b01010, 0b00100, 0b00100, 0b00100,
700 Glyph{0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000,
702 Glyph{0b01110, 0b01000, 0b01000, 0b01000, 0b01000, 0b01000,
704 Glyph{0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000,
706 Glyph{0b01110, 0b00010, 0b00010, 0b00010, 0b00010, 0b00010,
708 Glyph{0b00100, 0b01010, 0b10001, 0b00000, 0b00000, 0b00000,
710 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000,
712 Glyph{0b01000, 0b00100, 0b00010, 0b00000, 0b00000, 0b00000,
714 Glyph{0b00000, 0b00000, 0b01110, 0b00001, 0b01111, 0b10001,
716 Glyph{0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001,
718 Glyph{0b00000, 0b00000, 0b01110, 0b10000, 0b10000, 0b10001,
720 Glyph{0b00001, 0b00001, 0b01101, 0b10011, 0b10001, 0b10001,
722 Glyph{0b00000, 0b00000, 0b01110, 0b10001, 0b11111, 0b10000,
724 Glyph{0b00110, 0b01001, 0b01000, 0b11100, 0b01000, 0b01000,
726 Glyph{0b00000, 0b00000, 0b01111, 0b10001, 0b10001, 0b01111,
728 Glyph{0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001,
730 Glyph{0b00100, 0b00000, 0b01100, 0b00100, 0b00100, 0b00100,
732 Glyph{0b00010, 0b00000, 0b00110, 0b00010, 0b00010, 0b10010,
734 Glyph{0b10000, 0b10000, 0b10010, 0b10100, 0b11000, 0b10100,
736 Glyph{0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
738 Glyph{0b00000, 0b00000, 0b11010, 0b10101, 0b10101, 0b10101,
740 Glyph{0b00000, 0b00000, 0b10110, 0b11001, 0b10001, 0b10001,
742 Glyph{0b00000, 0b00000, 0b01110, 0b10001, 0b10001, 0b10001,
744 Glyph{0b00000, 0b00000, 0b11110, 0b10001, 0b11110, 0b10000,
746 Glyph{0b00000, 0b00000, 0b01101, 0b10001, 0b01111, 0b00001,
748 Glyph{0b00000, 0b00000, 0b10110, 0b11001, 0b10000, 0b10000,
750 Glyph{0b00000, 0b00000, 0b01111, 0b10000, 0b01110, 0b00001,
752 Glyph{0b01000, 0b01000, 0b11100, 0b01000, 0b01000, 0b01001,
754 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10001, 0b10011,
756 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10001, 0b01010,
758 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10101, 0b10101,
760 Glyph{0b00000, 0b00000, 0b10001, 0b01010, 0b00100, 0b01010,
762 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b01111, 0b00001,
764 Glyph{0b00000, 0b00000, 0b11111, 0b00010, 0b00100, 0b01000,
766 Glyph{0b00010, 0b00100, 0b00100, 0b01000, 0b00100, 0b00100,
768 Glyph{0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
770 Glyph{0b01000, 0b00100, 0b00100, 0b00010, 0b00100, 0b00100,
772 Glyph{0b00000, 0b00000, 0b01001, 0b10110, 0b00000, 0b00000,
BGR color stored in 16-bit BGR565 format.
Definition: BGR565.h:13
Fixed-size 5x7 bitmap font with ASCII and extended character support.
Definition: BitmapFont.h:22
static constexpr char kLastChar
Last directly stored ASCII character.
Definition: BitmapFont.h:39
const Glyph & glyph(CodePoint codePoint) const
Returns the glyph for a Unicode code point.
Definition: BitmapFont.h:47
void drawChar(ISurface< RGB_T > &target, int16_t x, int16_t y, char character, RGB_T foreground, RGB_T background=RGB_T(0), bool opaque=false, uint8_t scale=1) const
Draws a single character.
Definition: BitmapFont.h:74
static constexpr uint8_t kGlyphWidth
Width of a glyph in pixels.
Definition: BitmapFont.h:33
static constexpr char kFirstChar
First directly stored ASCII character.
Definition: BitmapFont.h:37
size_t measureTextHeight(const char *text, uint8_t scale=1, uint8_t lineSpacing=1) const
Returns the total text height in pixels.
Definition: BitmapFont.h:178
void drawText(ISurface< RGB_T > &target, int16_t x, int16_t y, const char *text, RGB_T foreground, RGB_T background=RGB_T(0), bool opaque=false, uint8_t scale=1, uint8_t spacing=1, uint8_t lineSpacing=1) const override
Draws a UTF-8 text string.
Definition: BitmapFont.h:106
static constexpr uint8_t kGlyphHeight
Height of a glyph in pixels.
Definition: BitmapFont.h:35
bool pixel(CodePoint codePoint, uint8_t x, uint8_t y) const
Returns whether a pixel is set in a code point glyph.
Definition: BitmapFont.h:64
size_t measureTextWidth(const char *text, uint8_t scale=1, uint8_t spacing=1) const
Returns the width of the longest text line in pixels.
Definition: BitmapFont.h:141
void drawCodePoint(ISurface< RGB_T > &target, int16_t x, int16_t y, CodePoint codePoint, RGB_T foreground, RGB_T background=RGB_T(0), bool opaque=false, uint8_t scale=1) const
Draws a single Unicode code point.
Definition: BitmapFont.h:83
const Glyph & glyph(char character) const
Returns the glyph for an 8-bit character.
Definition: BitmapFont.h:42
size_t getHeight(uint8_t scale) const
Returns the scaled glyph height in pixels.
Definition: BitmapFont.h:198
bool pixel(char character, uint8_t x, uint8_t y) const
Returns whether a pixel is set in an 8-bit character glyph.
Definition: BitmapFont.h:58
BitmapFont()=default
Creates a bitmap font instance.
Font rendering interface for TinyGPU-compatible framebuffers.
Definition: IFont.h:19
RGB color stored in 16-bit RGB565 format.
Definition: RGB565.h:13
RGB color stored in 24-bit RGB888 format.
Definition: RGB888.h:13
Definition: AVIWriter.h:9