fbpad: use FGCOLOR in tag summary
[fbpad.git] / pad.c
blob2bf485c2b8be869ffc0caa61b20de404f8edc0ec
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "config.h"
6 #include "draw.h"
7 #include "fbpad.h"
9 #define NCACHE (1 << 11)
10 #define MAXFBWIDTH (1 << 12)
12 static unsigned int cd[256] = {
13 COLOR0, COLOR1, COLOR2, COLOR3,
14 COLOR4, COLOR5, COLOR6, COLOR7,
15 COLOR8, COLOR9, COLOR10, COLOR11,
16 COLOR12, COLOR13, COLOR14, COLOR15};
17 static int rows, cols;
18 static int fnrows, fncols;
19 static struct font *fonts[3];
21 int pad_init(void)
23 int r, g, b;
24 if (fb_init())
25 return 1;
26 if (sizeof(fbval_t) != FBM_BPP(fb_mode())) {
27 fprintf(stderr, "pad_init: fbval_t doesn't match fb depth\n");
28 return 1;
30 if (pad_font(FR, FI, FB) < 0)
31 return -1;
32 fnrows = font_rows(fonts[0]);
33 fncols = font_cols(fonts[0]);
34 rows = fb_rows() / fnrows;
35 cols = fb_cols() / fncols;
36 for (r = 0; r < 6; r++) {
37 for (g = 0; g < 6; g++) {
38 for (b = 0; b < 6; b++) {
39 int idx = 16 + r * 36 + g * 6 + b;
40 cd[idx] = ((r * 40 + 55) << 16) |
41 ((g * 40 + 55) << 8) |
42 (b * 40 + 55);
46 for (r = 0; r < 24; r++)
47 cd[232 + r] = ((r * 10 + 8) << 16) |
48 ((r * 10 + 8) << 8) | (r * 10 + 8);
49 return 0;
52 void pad_free(void)
54 int i;
55 for (i = 0; i < 3; i++)
56 if (fonts[i])
57 font_free(fonts[i]);
58 fb_free();
61 #define CR(a) (((a) >> 16) & 0x0000ff)
62 #define CG(a) (((a) >> 8) & 0x0000ff)
63 #define CB(a) ((a) & 0x0000ff)
64 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
66 static unsigned mixed_color(int fg, int bg, unsigned val)
68 unsigned int fore = cd[fg], back = cd[bg];
69 unsigned char r = COLORMERGE(CR(fore), CR(back), val);
70 unsigned char g = COLORMERGE(CG(fore), CG(back), val);
71 unsigned char b = COLORMERGE(CB(fore), CB(back), val);
72 return FB_VAL(r, g, b);
75 static unsigned color2fb(int c)
77 return FB_VAL(CR(cd[c]), CG(cd[c]), CB(cd[c]));
80 static fbval_t cache[NCACHE][NDOTS];
81 static struct glyph {
82 int c;
83 short fg, bg;
84 } glyphs[NCACHE];
86 static struct glyph *glyph_entry(int c, int fg, int bg)
88 return &glyphs[((c - 32) ^ (fg << 6) ^ (bg << 5)) & (NCACHE - 1)];
91 static fbval_t *glyph_cache(int c, short fg, short bg)
93 struct glyph *g = glyph_entry(c, fg, bg);
94 if (g->c == c && g->fg == fg && g->bg == bg)
95 return cache[g - glyphs];
96 return NULL;
99 static fbval_t *glyph_add(int c, short fg, short bg)
101 struct glyph *g = glyph_entry(c, fg, bg);
102 g->c = c;
103 g->fg = fg;
104 g->bg = bg;
105 return cache[g - glyphs];
108 static void bmp2fb(fbval_t *d, char *s, int fg, int bg, int nr, int nc)
110 int i, j;
111 for (i = 0; i < fnrows; i++) {
112 for (j = 0; j < fncols; j++) {
113 unsigned v = i < nr && j < nc ?
114 (unsigned char) s[i * nc + j] : 0;
115 d[i * fncols + j] = mixed_color(fg, bg, v);
120 static fbval_t *ch2fb(int fn, int c, short fg, short bg)
122 char bits[NDOTS];
123 fbval_t *fbbits;
124 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
125 return NULL;
126 if ((fbbits = glyph_cache(c, fg, bg)))
127 return fbbits;
128 if (font_bitmap(fonts[fn], bits, c))
129 return NULL;
130 fbbits = glyph_add(c, fg, bg);
131 bmp2fb(fbbits, bits, fg & FN_C, bg & FN_C,
132 font_rows(fonts[fn]), font_cols(fonts[fn]));
133 return fbbits;
136 static void fb_box(int sr, int sc, int er, int ec, fbval_t val)
138 static fbval_t line[MAXFBWIDTH];
139 int cn = ec - sc;
140 int i;
141 for (i = 0; i < cn; i++)
142 line[i] = val;
143 for (i = sr; i < er; i++)
144 fb_set(i, sc, line, cn);
147 static int fnsel(int fg, int bg)
149 if ((fg | bg) & FN_B)
150 return fonts[2] ? 2 : 0;
151 if ((fg | bg) & FN_I)
152 return fonts[1] ? 1 : 0;
153 return 0;
156 void pad_put(int ch, int r, int c, int fg, int bg)
158 int sr = fnrows * r;
159 int sc = fncols * c;
160 fbval_t *bits;
161 int i;
162 if ((fg & 0xfff8) == FN_B && !fonts[2])
163 fg |= 8; /* increase intensity of no FB */
164 bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
165 if (!bits)
166 bits = ch2fb(0, ch, fg, bg);
167 if (!bits)
168 fb_box(sr, sc, sr + fnrows, sc + fncols, color2fb(bg & FN_C));
169 else
170 for (i = 0; i < fnrows; i++)
171 fb_set(sr + i, sc, bits + (i * fncols), fncols);
174 void pad_blank(int c)
176 fb_box(0, 0, fb_rows(), fb_cols(), color2fb(c & FN_C));
179 void pad_blankrow(int r, int bg)
181 int sr = r * fnrows;
182 int er = r == rows - 1 ? fb_rows() : (r + 1) * fnrows;
183 fb_box(sr, 0, er, fb_cols(), color2fb(bg & FN_C));
186 int pad_rows(void)
188 return rows;
191 int pad_cols(void)
193 return cols;
196 int pad_font(char *fr, char *fi, char *fb)
198 char *fns[] = {fr, fi, fb};
199 int i;
200 for (i = 0; i < 3; i++) {
201 if (fonts[i])
202 font_free(fonts[i]);
203 fonts[i] = fns[i] ? font_open(fns[i]) : NULL;
205 memset(glyphs, 0, sizeof(glyphs));
206 if (!fonts[0])
207 fprintf(stderr, "pad: bad font <%s>\n", fr);
208 return fonts[0] ? 0 : -1;