TinyGPU
Loading...
Searching...
No Matches
BitmapFont.h
Go to the documentation of this file.
1#pragma once
2
3#include <stddef.h>
4#include <stdint.h>
5
6#include <array>
7#include "RGB565.h"
8#include "RGB888.h"
9#include "BGR565.h"
10#include "IFont.h"
11#include "ISurface.h"
12
13namespace tinygpu {
14
15/**
16 * @brief Fixed-size 5x7 bitmap font with ASCII and extended character support.
17 *
18 * The font can inspect glyph data, measure text, and render UTF-8 strings to
19 * any framebuffer implementation that follows the TinyGPU font interface.
20 */
21template <typename RGB_T = RGB565>
22class BitmapFont : public IFont<RGB_T> {
23 public:
24 /// Glyph storage for one 5x7 character.
25 using Glyph = std::array<uint8_t, 7>;
26 /// Unicode code point type used during UTF-8 decoding.
27 using CodePoint = uint32_t;
28
29 /// Creates a bitmap font instance.
30 BitmapFont() = default;
31
32 /// Width of a glyph in pixels.
33 static constexpr uint8_t kGlyphWidth = 5;
34 /// Height of a glyph in pixels.
35 static constexpr uint8_t kGlyphHeight = 7;
36 /// First directly stored ASCII character.
37 static constexpr char kFirstChar = ' ';
38 /// Last directly stored ASCII character.
39 static constexpr char kLastChar = '~';
40
41 /// Returns the glyph for an 8-bit character.
42 const Glyph& glyph(char character) const {
43 return glyph(static_cast<CodePoint>(static_cast<unsigned char>(character)));
44 }
45
46 /// Returns the glyph for a Unicode code point.
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)];
51 }
52
53 const Glyph* mappedGlyph = glyphForExtendedCodePoint(codePoint);
54 return mappedGlyph != nullptr ? *mappedGlyph : replacementGlyph();
55 }
56
57 /// Returns whether a pixel is set in an 8-bit character glyph.
58 bool pixel(char character, uint8_t x, uint8_t y) const {
59 return pixel(static_cast<CodePoint>(static_cast<unsigned char>(character)),
60 x, y);
61 }
62
63 /// Returns whether a pixel is set in a code point glyph.
64 bool pixel(CodePoint codePoint, uint8_t x, uint8_t y) const {
65 if (x >= kGlyphWidth || y >= kGlyphHeight) {
66 return false;
67 }
68
69 const uint8_t rowMask = glyph(codePoint)[y];
70 return (rowMask & static_cast<uint8_t>(1U << (kGlyphWidth - 1 - x))) != 0;
71 }
72
73 /// Draws a single character.
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 {
77 drawCodePoint(target, x, y,
78 static_cast<CodePoint>(static_cast<unsigned char>(character)),
79 foreground, background, opaque, scale);
80 }
81
82 /// Draws a single Unicode code point.
83 void drawCodePoint(ISurface<RGB_T>& target, int16_t x, int16_t y,
84 CodePoint codePoint, RGB_T foreground,
85 RGB_T background = RGB_T(0), bool opaque = false,
86 uint8_t scale = 1) const {
87 if (scale == 0) {
88 scale = 1;
89 }
90
91 for (uint8_t row = 0; row < kGlyphHeight; ++row) {
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));
95
96 if (pixel(codePoint, column, row)) {
97 target.fillRect(pixelX, pixelY, scale, scale, foreground);
98 } else if (opaque) {
99 target.fillRect(pixelX, pixelY, scale, scale, background);
100 }
101 }
102 }
103 }
104
105 /// Draws a UTF-8 text string.
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) {
111 return;
112 }
113 if (scale == 0) {
114 scale = 1;
115 }
116
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);
121
122 int16_t cursorX = x;
123 int16_t cursorY = y;
124 const char* current = text;
125 while (*current != '\0') {
126 if (*current == '\n') {
127 ++current;
128 cursorX = x;
129 cursorY = static_cast<int16_t>(cursorY + advanceY);
130 continue;
131 }
132
133 const CodePoint codePoint = decodeNextUtf8(current);
134 drawCodePoint(target, cursorX, cursorY, codePoint, foreground, background,
135 opaque, scale);
136 cursorX = static_cast<int16_t>(cursorX + advanceX);
137 }
138 }
139
140 /// Returns the width of the longest text line in pixels.
142 uint8_t spacing = 1) const {
143 if (text == nullptr || *text == '\0') {
144 return 0;
145 }
146 if (scale == 0) {
147 scale = 1;
148 }
149
150 size_t lineLength = 0;
151 size_t longestLine = 0;
152 const char* current = text;
153 while (*current != '\0') {
154 if (*current == '\n') {
155 ++current;
156 if (lineLength > longestLine) {
157 longestLine = lineLength;
158 }
159 lineLength = 0;
160 } else {
161 decodeNextUtf8(current);
162 ++lineLength;
163 }
164 }
165
166 if (lineLength > longestLine) {
167 longestLine = lineLength;
168 }
169
170 if (longestLine == 0) {
171 return 0;
172 }
173
174 return (longestLine * kGlyphWidth * scale) + ((longestLine - 1) * spacing);
175 }
176
177 /// Returns the total text height in pixels.
179 uint8_t lineSpacing = 1) const {
180 if (text == nullptr || *text == '\0') {
181 return 0;
182 }
183 if (scale == 0) {
184 scale = 1;
185 }
186
187 size_t lines = 1;
188 for (const char* current = text; *current != '\0'; ++current) {
189 if (*current == '\n') {
190 ++lines;
191 }
192 }
193
194 return (lines * kGlyphHeight * scale) + ((lines - 1) * lineSpacing);
195 }
196
197 /// Returns the scaled glyph height in pixels.
199 return (kGlyphHeight * scale);
200 }
201
202 private:
203 size_t glyphIndex(CodePoint codePoint) const {
204 if (codePoint < static_cast<unsigned char>(kFirstChar) ||
205 codePoint > static_cast<unsigned char>(kLastChar)) {
206 return 0;
207 }
208 return codePoint - static_cast<unsigned char>(kFirstChar);
209 }
210
211 const Glyph& replacementGlyph() const {
212 return glyphTable()[glyphIndex(static_cast<CodePoint>('?'))];
213 }
214
215 const Glyph& asciiGlyph(char character) const {
216 return glyphTable()[glyphIndex(
217 static_cast<CodePoint>(static_cast<unsigned char>(character)))];
218 }
219
220 const Glyph* asciiGlyphPtr(char character) const {
221 return &asciiGlyph(character);
222 }
223
224 const Glyph* glyphForExtendedCodePoint(CodePoint codePoint) const {
225 switch (codePoint) {
226 case 0x80:
227 case 0x20AC:
228 return &euroGlyph();
229 case 0x82:
230 case 0x201A:
231 return asciiGlyphPtr(',');
232 case 0x83:
233 case 0x0192:
234 return asciiGlyphPtr('f');
235 case 0x84:
236 case 0x201E:
237 return asciiGlyphPtr('"');
238 case 0x85:
239 case 0x2026:
240 return asciiGlyphPtr('.');
241 case 0x86:
242 case 0x2020:
243 case 0x87:
244 case 0x2021:
245 return asciiGlyphPtr('+');
246 case 0x88:
247 case 0x02C6:
248 return asciiGlyphPtr('^');
249 case 0x89:
250 case 0x2030:
251 return asciiGlyphPtr('%');
252 case 0x8A:
253 case 0x0160:
254 return asciiGlyphPtr('S');
255 case 0x8B:
256 case 0x2039:
257 return asciiGlyphPtr('<');
258 case 0x8C:
259 case 0x0152:
260 return asciiGlyphPtr('O');
261 case 0x8E:
262 case 0x017D:
263 return asciiGlyphPtr('Z');
264 case 0x91:
265 case 0x2018:
266 case 0x92:
267 case 0x2019:
268 return asciiGlyphPtr('\'');
269 case 0x93:
270 case 0x201C:
271 case 0x94:
272 case 0x201D:
273 return asciiGlyphPtr('"');
274 case 0x95:
275 case 0x2022:
276 return bulletGlyphPtr();
277 case 0x96:
278 case 0x2013:
279 case 0x97:
280 case 0x2014:
281 return asciiGlyphPtr('-');
282 case 0x98:
283 case 0x02DC:
284 return asciiGlyphPtr('~');
285 case 0x99:
286 case 0x2122:
287 return asciiGlyphPtr('T');
288 case 0x9A:
289 case 0x0161:
290 return asciiGlyphPtr('s');
291 case 0x9B:
292 case 0x203A:
293 return asciiGlyphPtr('>');
294 case 0x9C:
295 case 0x0153:
296 return asciiGlyphPtr('o');
297 case 0x9E:
298 case 0x017E:
299 return asciiGlyphPtr('z');
300 case 0x9F:
301 case 0x0178:
302 return asciiGlyphPtr('Y');
303 case 0xA0:
304 return asciiGlyphPtr(' ');
305 case 0xA1:
306 return asciiGlyphPtr('!');
307 case 0xA2:
308 return &centGlyph();
309 case 0xA3:
310 return &sterlingGlyph();
311 case 0xA4:
312 return asciiGlyphPtr('$');
313 case 0xA5:
314 return &yenGlyph();
315 case 0xA6:
316 return asciiGlyphPtr('|');
317 case 0xA7:
318 return &sectionGlyph();
319 case 0xA8:
320 return asciiGlyphPtr('"');
321 case 0xA9:
322 return &copyrightGlyph();
323 case 0xAA:
324 return asciiGlyphPtr('a');
325 case 0xAB:
326 return asciiGlyphPtr('<');
327 case 0xAC:
328 return &notGlyph();
329 case 0xAD:
330 return asciiGlyphPtr('-');
331 case 0xAE:
332 return asciiGlyphPtr('R');
333 case 0xAF:
334 return asciiGlyphPtr('-');
335 case 0xB0:
336 return &degreeGlyph();
337 case 0xB1:
338 return &plusMinusGlyph();
339 case 0xB2:
340 return asciiGlyphPtr('2');
341 case 0xB3:
342 return asciiGlyphPtr('3');
343 case 0xB4:
344 return asciiGlyphPtr('\'');
345 case 0xB5:
346 return &microGlyph();
347 case 0xB6:
348 return &paragraphGlyph();
349 case 0xB7:
350 return bulletGlyphPtr();
351 case 0xB8:
352 return asciiGlyphPtr(',');
353 case 0xB9:
354 return asciiGlyphPtr('1');
355 case 0xBA:
356 return asciiGlyphPtr('o');
357 case 0xBB:
358 return asciiGlyphPtr('>');
359 case 0xBC:
360 case 0xBD:
361 case 0xBE:
362 return asciiGlyphPtr('/');
363 case 0xBF:
364 return asciiGlyphPtr('?');
365 case 0xC0:
366 case 0xC1:
367 case 0xC2:
368 case 0xC3:
369 case 0xC4:
370 case 0xC5:
371 case 0xC6:
372 return asciiGlyphPtr('A');
373 case 0xC7:
374 return asciiGlyphPtr('C');
375 case 0xC8:
376 case 0xC9:
377 case 0xCA:
378 case 0xCB:
379 return asciiGlyphPtr('E');
380 case 0xCC:
381 case 0xCD:
382 case 0xCE:
383 case 0xCF:
384 return asciiGlyphPtr('I');
385 case 0xD0:
386 return asciiGlyphPtr('D');
387 case 0xD1:
388 return asciiGlyphPtr('N');
389 case 0xD2:
390 case 0xD3:
391 case 0xD4:
392 case 0xD5:
393 case 0xD6:
394 case 0xD8:
395 return asciiGlyphPtr('O');
396 case 0xD7:
397 return &multiplyGlyph();
398 case 0xD9:
399 case 0xDA:
400 case 0xDB:
401 case 0xDC:
402 return asciiGlyphPtr('U');
403 case 0xDD:
404 return asciiGlyphPtr('Y');
405 case 0xDE:
406 return asciiGlyphPtr('P');
407 case 0xDF:
408 return asciiGlyphPtr('B');
409 case 0xE0:
410 case 0xE1:
411 case 0xE2:
412 case 0xE3:
413 case 0xE4:
414 case 0xE5:
415 case 0xE6:
416 return asciiGlyphPtr('a');
417 case 0xE7:
418 return asciiGlyphPtr('c');
419 case 0xE8:
420 case 0xE9:
421 case 0xEA:
422 case 0xEB:
423 return asciiGlyphPtr('e');
424 case 0xEC:
425 case 0xED:
426 case 0xEE:
427 case 0xEF:
428 return asciiGlyphPtr('i');
429 case 0xF0:
430 return asciiGlyphPtr('d');
431 case 0xF1:
432 return asciiGlyphPtr('n');
433 case 0xF2:
434 case 0xF3:
435 case 0xF4:
436 case 0xF5:
437 case 0xF6:
438 case 0xF8:
439 return asciiGlyphPtr('o');
440 case 0xF7:
441 return &divideGlyph();
442 case 0xF9:
443 case 0xFA:
444 case 0xFB:
445 case 0xFC:
446 return asciiGlyphPtr('u');
447 case 0xFD:
448 case 0xFF:
449 return asciiGlyphPtr('y');
450 case 0xFE:
451 return asciiGlyphPtr('p');
452 default:
453 return nullptr;
454 }
455 }
456
457 const Glyph* bulletGlyphPtr() const {
458 static const Glyph glyph = {0b00000, 0b00100, 0b01110, 0b01110,
459 0b01110, 0b00100, 0b00000};
460 return &glyph;
461 }
462
463 const Glyph& euroGlyph() const {
464 static const Glyph glyph = {0b00110, 0b01001, 0b11100, 0b11110,
465 0b11100, 0b01001, 0b00110};
466 return glyph;
467 }
468
469 const Glyph& centGlyph() const {
470 static const Glyph glyph = {0b00100, 0b01110, 0b10100, 0b10000,
471 0b10100, 0b01110, 0b00100};
472 return glyph;
473 }
474
475 const Glyph& sterlingGlyph() const {
476 static const Glyph glyph = {0b00110, 0b01001, 0b01000, 0b11100,
477 0b01000, 0b11111, 0b01000};
478 return glyph;
479 }
480
481 const Glyph& yenGlyph() const {
482 static const Glyph glyph = {0b10001, 0b01010, 0b11111, 0b00100,
483 0b11111, 0b00100, 0b00100};
484 return glyph;
485 }
486
487 const Glyph& sectionGlyph() const {
488 static const Glyph glyph = {0b01110, 0b10000, 0b01100, 0b00010,
489 0b00110, 0b00001, 0b11110};
490 return glyph;
491 }
492
493 const Glyph& copyrightGlyph() const {
494 static const Glyph glyph = {0b01110, 0b10001, 0b10111, 0b10101,
495 0b10111, 0b10001, 0b01110};
496 return glyph;
497 }
498
499 const Glyph& notGlyph() const {
500 static const Glyph glyph = {0b00000, 0b00000, 0b11111, 0b00001,
501 0b00001, 0b00000, 0b00000};
502 return glyph;
503 }
504
505 const Glyph& degreeGlyph() const {
506 static const Glyph glyph = {0b00110, 0b01001, 0b01001, 0b00110,
507 0b00000, 0b00000, 0b00000};
508 return glyph;
509 }
510
511 const Glyph& plusMinusGlyph() const {
512 static const Glyph glyph = {0b00000, 0b00100, 0b00100, 0b11111,
513 0b00100, 0b11111, 0b00000};
514 return glyph;
515 }
516
517 const Glyph& microGlyph() const {
518 static const Glyph glyph = {0b10001, 0b10001, 0b10001, 0b10011,
519 0b01101, 0b10000, 0b10000};
520 return glyph;
521 }
522
523 const Glyph& paragraphGlyph() const {
524 static const Glyph glyph = {0b11110, 0b10110, 0b10110, 0b11110,
525 0b00100, 0b00100, 0b00100};
526 return glyph;
527 }
528
529 const Glyph& multiplyGlyph() const {
530 static const Glyph glyph = {0b00000, 0b10001, 0b01010, 0b00100,
531 0b01010, 0b10001, 0b00000};
532 return glyph;
533 }
534
535 const Glyph& divideGlyph() const {
536 static const Glyph glyph = {0b00000, 0b00100, 0b00000, 0b11111,
537 0b00000, 0b00100, 0b00000};
538 return glyph;
539 }
540
541 CodePoint decodeNextUtf8(const char*& current) const {
542 const unsigned char firstByte = static_cast<unsigned char>(*current);
543 if (firstByte == 0) {
544 return 0;
545 }
546
547 if ((firstByte & 0x80U) == 0) {
548 ++current;
549 return static_cast<CodePoint>(firstByte);
550 }
551
552 uint8_t sequenceLength = 0;
553 CodePoint codePoint = 0;
554 if ((firstByte & 0xE0U) == 0xC0U) {
555 sequenceLength = 2;
556 codePoint = static_cast<CodePoint>(firstByte & 0x1FU);
557 } else if ((firstByte & 0xF0U) == 0xE0U) {
558 sequenceLength = 3;
559 codePoint = static_cast<CodePoint>(firstByte & 0x0FU);
560 } else if ((firstByte & 0xF8U) == 0xF0U) {
561 sequenceLength = 4;
562 codePoint = static_cast<CodePoint>(firstByte & 0x07U);
563 } else {
564 ++current;
565 return static_cast<CodePoint>('?');
566 }
567
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) {
571 ++current;
572 return static_cast<CodePoint>('?');
573 }
574
575 codePoint = static_cast<CodePoint>((codePoint << 6) | (nextByte & 0x3FU));
576 }
577
578 current += sequenceLength;
579 return codePoint;
580 }
581
582 const Glyph* glyphTable() const {
583 static const Glyph kGlyphs[] = {
584 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000,
585 0b00000}, // ' '
586 Glyph{0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00000,
587 0b00100}, // '!'
588 Glyph{0b01010, 0b01010, 0b01010, 0b00000, 0b00000, 0b00000,
589 0b00000}, // '"'
590 Glyph{0b01010, 0b01010, 0b11111, 0b01010, 0b11111, 0b01010,
591 0b01010}, // '#'
592 Glyph{0b00100, 0b01111, 0b10100, 0b01110, 0b00101, 0b11110,
593 0b00100}, // '$'
594 Glyph{0b11001, 0b11010, 0b00100, 0b01000, 0b10110, 0b00110,
595 0b00000}, // '%'
596 Glyph{0b01100, 0b10010, 0b10100, 0b01000, 0b10101, 0b10010,
597 0b01101}, // '&'
598 Glyph{0b00100, 0b00100, 0b00100, 0b00000, 0b00000, 0b00000,
599 0b00000}, // '\''
600 Glyph{0b00010, 0b00100, 0b01000, 0b01000, 0b01000, 0b00100,
601 0b00010}, // '('
602 Glyph{0b01000, 0b00100, 0b00010, 0b00010, 0b00010, 0b00100,
603 0b01000}, // ')'
604 Glyph{0b00000, 0b10101, 0b01110, 0b11111, 0b01110, 0b10101,
605 0b00000}, // '*'
606 Glyph{0b00000, 0b00100, 0b00100, 0b11111, 0b00100, 0b00100,
607 0b00000}, // '+'
608 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00100, 0b00100,
609 0b01000}, // ','
610 Glyph{0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000,
611 0b00000}, // '-'
612 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00100,
613 0b00100}, // '.'
614 Glyph{0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b00000,
615 0b00000}, // '/'
616 Glyph{0b01110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001,
617 0b01110}, // '0'
618 Glyph{0b00100, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100,
619 0b01110}, // '1'
620 Glyph{0b01110, 0b10001, 0b00001, 0b00010, 0b00100, 0b01000,
621 0b11111}, // '2'
622 Glyph{0b11110, 0b00001, 0b00001, 0b01110, 0b00001, 0b00001,
623 0b11110}, // '3'
624 Glyph{0b00010, 0b00110, 0b01010, 0b10010, 0b11111, 0b00010,
625 0b00010}, // '4'
626 Glyph{0b11111, 0b10000, 0b11110, 0b00001, 0b00001, 0b10001,
627 0b01110}, // '5'
628 Glyph{0b00110, 0b01000, 0b10000, 0b11110, 0b10001, 0b10001,
629 0b01110}, // '6'
630 Glyph{0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b01000,
631 0b01000}, // '7'
632 Glyph{0b01110, 0b10001, 0b10001, 0b01110, 0b10001, 0b10001,
633 0b01110}, // '8'
634 Glyph{0b01110, 0b10001, 0b10001, 0b01111, 0b00001, 0b00010,
635 0b01100}, // '9'
636 Glyph{0b00000, 0b00100, 0b00100, 0b00000, 0b00100, 0b00100,
637 0b00000}, // ':'
638 Glyph{0b00000, 0b00100, 0b00100, 0b00000, 0b00100, 0b00100,
639 0b01000}, // ';'
640 Glyph{0b00010, 0b00100, 0b01000, 0b10000, 0b01000, 0b00100,
641 0b00010}, // '<'
642 Glyph{0b00000, 0b00000, 0b11111, 0b00000, 0b11111, 0b00000,
643 0b00000}, // '='
644 Glyph{0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100,
645 0b01000}, // '>'
646 Glyph{0b01110, 0b10001, 0b00001, 0b00010, 0b00100, 0b00000,
647 0b00100}, // '?'
648 Glyph{0b01110, 0b10001, 0b00001, 0b01101, 0b10101, 0b10101,
649 0b01110}, // '@'
650 Glyph{0b01110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001,
651 0b10001}, // 'A'
652 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001,
653 0b11110}, // 'B'
654 Glyph{0b01110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001,
655 0b01110}, // 'C'
656 Glyph{0b11100, 0b10010, 0b10001, 0b10001, 0b10001, 0b10010,
657 0b11100}, // 'D'
658 Glyph{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000,
659 0b11111}, // 'E'
660 Glyph{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000,
661 0b10000}, // 'F'
662 Glyph{0b01110, 0b10001, 0b10000, 0b10111, 0b10001, 0b10001,
663 0b01111}, // 'G'
664 Glyph{0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001,
665 0b10001}, // 'H'
666 Glyph{0b01110, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
667 0b01110}, // 'I'
668 Glyph{0b00001, 0b00001, 0b00001, 0b00001, 0b10001, 0b10001,
669 0b01110}, // 'J'
670 Glyph{0b10001, 0b10010, 0b10100, 0b11000, 0b10100, 0b10010,
671 0b10001}, // 'K'
672 Glyph{0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000,
673 0b11111}, // 'L'
674 Glyph{0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001,
675 0b10001}, // 'M'
676 Glyph{0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001,
677 0b10001}, // 'N'
678 Glyph{0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001,
679 0b01110}, // 'O'
680 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000,
681 0b10000}, // 'P'
682 Glyph{0b01110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10010,
683 0b01101}, // 'Q'
684 Glyph{0b11110, 0b10001, 0b10001, 0b11110, 0b10100, 0b10010,
685 0b10001}, // 'R'
686 Glyph{0b01111, 0b10000, 0b10000, 0b01110, 0b00001, 0b00001,
687 0b11110}, // 'S'
688 Glyph{0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
689 0b00100}, // 'T'
690 Glyph{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001,
691 0b01110}, // 'U'
692 Glyph{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01010,
693 0b00100}, // 'V'
694 Glyph{0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b10101,
695 0b01010}, // 'W'
696 Glyph{0b10001, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001,
697 0b10001}, // 'X'
698 Glyph{0b10001, 0b10001, 0b01010, 0b00100, 0b00100, 0b00100,
699 0b00100}, // 'Y'
700 Glyph{0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000,
701 0b11111}, // 'Z'
702 Glyph{0b01110, 0b01000, 0b01000, 0b01000, 0b01000, 0b01000,
703 0b01110}, // '['
704 Glyph{0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000,
705 0b00000}, // '\\'
706 Glyph{0b01110, 0b00010, 0b00010, 0b00010, 0b00010, 0b00010,
707 0b01110}, // ']'
708 Glyph{0b00100, 0b01010, 0b10001, 0b00000, 0b00000, 0b00000,
709 0b00000}, // '^'
710 Glyph{0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000,
711 0b11111}, // '_'
712 Glyph{0b01000, 0b00100, 0b00010, 0b00000, 0b00000, 0b00000,
713 0b00000}, // '`'
714 Glyph{0b00000, 0b00000, 0b01110, 0b00001, 0b01111, 0b10001,
715 0b01111}, // 'a'
716 Glyph{0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001,
717 0b11110}, // 'b'
718 Glyph{0b00000, 0b00000, 0b01110, 0b10000, 0b10000, 0b10001,
719 0b01110}, // 'c'
720 Glyph{0b00001, 0b00001, 0b01101, 0b10011, 0b10001, 0b10001,
721 0b01111}, // 'd'
722 Glyph{0b00000, 0b00000, 0b01110, 0b10001, 0b11111, 0b10000,
723 0b01110}, // 'e'
724 Glyph{0b00110, 0b01001, 0b01000, 0b11100, 0b01000, 0b01000,
725 0b01000}, // 'f'
726 Glyph{0b00000, 0b00000, 0b01111, 0b10001, 0b10001, 0b01111,
727 0b00001}, // 'g'
728 Glyph{0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001,
729 0b10001}, // 'h'
730 Glyph{0b00100, 0b00000, 0b01100, 0b00100, 0b00100, 0b00100,
731 0b01110}, // 'i'
732 Glyph{0b00010, 0b00000, 0b00110, 0b00010, 0b00010, 0b10010,
733 0b01100}, // 'j'
734 Glyph{0b10000, 0b10000, 0b10010, 0b10100, 0b11000, 0b10100,
735 0b10010}, // 'k'
736 Glyph{0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
737 0b01110}, // 'l'
738 Glyph{0b00000, 0b00000, 0b11010, 0b10101, 0b10101, 0b10101,
739 0b10101}, // 'm'
740 Glyph{0b00000, 0b00000, 0b10110, 0b11001, 0b10001, 0b10001,
741 0b10001}, // 'n'
742 Glyph{0b00000, 0b00000, 0b01110, 0b10001, 0b10001, 0b10001,
743 0b01110}, // 'o'
744 Glyph{0b00000, 0b00000, 0b11110, 0b10001, 0b11110, 0b10000,
745 0b10000}, // 'p'
746 Glyph{0b00000, 0b00000, 0b01101, 0b10001, 0b01111, 0b00001,
747 0b00001}, // 'q'
748 Glyph{0b00000, 0b00000, 0b10110, 0b11001, 0b10000, 0b10000,
749 0b10000}, // 'r'
750 Glyph{0b00000, 0b00000, 0b01111, 0b10000, 0b01110, 0b00001,
751 0b11110}, // 's'
752 Glyph{0b01000, 0b01000, 0b11100, 0b01000, 0b01000, 0b01001,
753 0b00110}, // 't'
754 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10001, 0b10011,
755 0b01101}, // 'u'
756 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10001, 0b01010,
757 0b00100}, // 'v'
758 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b10101, 0b10101,
759 0b01010}, // 'w'
760 Glyph{0b00000, 0b00000, 0b10001, 0b01010, 0b00100, 0b01010,
761 0b10001}, // 'x'
762 Glyph{0b00000, 0b00000, 0b10001, 0b10001, 0b01111, 0b00001,
763 0b11110}, // 'y'
764 Glyph{0b00000, 0b00000, 0b11111, 0b00010, 0b00100, 0b01000,
765 0b11111}, // 'z'
766 Glyph{0b00010, 0b00100, 0b00100, 0b01000, 0b00100, 0b00100,
767 0b00010}, // '{'
768 Glyph{0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100,
769 0b00100}, // '|'
770 Glyph{0b01000, 0b00100, 0b00100, 0b00010, 0b00100, 0b00100,
771 0b01000}, // '}'
772 Glyph{0b00000, 0b00000, 0b01001, 0b10110, 0b00000, 0b00000,
773 0b00000}, // '~'
774 };
775
776 return kGlyphs;
777 }
778};
779
780static BitmapFont<RGB565> FontRGB565;
781static BitmapFont<RGB888> FontRGB888;
782static BitmapFont<BGR565> FontBGR565;
783static BitmapFont<bool> FontMonochrome;
784
785} // namespace tinygpu
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