Add VCS links
[debian-dgen.git] / sdl / font.cpp
blobf9c5cfb3831485e2c9daa01e31f5f4b6a2ccdfbe
1 /**
2 * DGen's font renderer.
3 */
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <assert.h>
9 #include "font.h" /* The interface functions */
11 #ifndef FONT_VISIBLE
12 #define FONT_VISIBLE 24
13 #endif
15 extern const short *dgen_font_8x13[0x80];
16 extern const short *dgen_font_16x26[0x80];
17 extern const short *dgen_font_7x5[0x80];
19 const struct dgen_font dgen_font[] = {
20 { 16, 26, &dgen_font_16x26 },
21 { 8, 13, &dgen_font_8x13 },
22 { 7, 5, &dgen_font_7x5 },
23 { 0, 0, NULL }
26 const struct dgen_font *font_select(unsigned int max_width,
27 unsigned int max_height,
28 enum font_type type)
30 const struct dgen_font *font = dgen_font;
32 assert(type <= FONT_TYPE_AUTO);
33 if (type != FONT_TYPE_AUTO) {
34 // Make sure we're able to display at least one character.
35 font = &font[type];
36 if ((max_width < font->w) || (max_height < font->h))
37 return NULL;
38 return font;
40 // Chose a font able to display at least FONT_VISIBLE characters.
41 while ((font->data != NULL) &&
42 ((font->h > max_height) ||
43 ((max_width / font->w) < FONT_VISIBLE))) {
44 ++font;
45 continue;
47 if (font->data == NULL)
48 return NULL;
49 return font;
52 static void font_mark(uint8_t *buf,
53 unsigned int max_width, unsigned int max_height,
54 unsigned int bytes_per_pixel, unsigned int pitch,
55 unsigned int mark_x,
56 unsigned int font_w, unsigned int font_h)
58 unsigned int y;
60 if (((mark_x + font_w) > max_width) || (max_height < font_h))
61 return;
62 buf += (mark_x * bytes_per_pixel);
63 for (y = 0; (y != font_h); ++y) {
64 unsigned int x;
65 unsigned int len = (bytes_per_pixel * font_w);
67 for (x = 0; (x < len); ++x)
68 buf[x] ^= 0xff;
69 buf += pitch;
73 size_t font_text_width(const char *msg, size_t len,
74 unsigned int max_width, unsigned int max_height,
75 enum font_type type)
77 const struct dgen_font *font =
78 font_select(max_width, max_height, type);
79 size_t width = 0;
81 if (font == NULL)
82 return 0;
83 while ((*msg != '\0') && (len)) {
84 width += font->w;
85 ++msg;
86 --len;
88 return width;
91 size_t font_text_max_len(unsigned int max_width, unsigned int max_height,
92 enum font_type type)
94 const struct dgen_font *font =
95 font_select(max_width, max_height, type);
97 if (font == NULL)
98 return ~(size_t)0;
99 return (max_width / font->w);
102 size_t font_text(uint8_t *buf,
103 unsigned int max_width, unsigned int max_height,
104 unsigned int bytes_per_pixel, unsigned int pitch,
105 const char *msg, size_t len, unsigned int mark,
106 enum font_type type)
108 const struct dgen_font *font;
109 uint8_t *p_max;
110 size_t r;
111 unsigned int x;
113 if (len == 0)
114 return 0;
115 if ((font = font_select(max_width, max_height, type)) == NULL) {
116 printf("info: %.*s\n", (unsigned int)len, msg);
117 if (mark <= len) {
118 printf(" ");
119 for (x = 0; (x != mark); ++x)
120 putchar(' ');
121 puts("^");
123 return len;
125 p_max = (buf + (pitch * max_height));
126 for (x = 0, r = 0;
127 ((msg[r] != '\0') && (r != len) && ((x + font->w) <= max_width));
128 ++r, x += font->w) {
129 const short *glyph = (*font->data)[(msg[r] & 0x7f)];
130 uint8_t *p = (buf + (x * bytes_per_pixel));
131 unsigned int n = 0;
132 short g;
134 if (glyph == NULL)
135 continue;
136 while ((g = *glyph) != -1) {
137 unsigned int i;
139 p += (((n += g) / font->w) * pitch);
140 n %= font->w;
141 for (i = 0; (i < bytes_per_pixel); ++i) {
142 uint8_t *tmp = &p[((n * bytes_per_pixel) + i)];
144 if (tmp < p_max)
145 *tmp = 0xff;
147 ++glyph;
149 if (r == mark)
150 font_mark(buf, max_width, max_height, bytes_per_pixel,
151 pitch, x, font->w, font->h);
153 if (r == mark)
154 font_mark(buf, max_width, max_height, bytes_per_pixel, pitch,
155 x, font->w, font->h);
156 return r;