fbpad: new tag listing
[fbpad.git] / pad.c
blobaef0263d537abcda1bc7e49736aa4f6cac699b9a
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 static unsigned int cd[256] = {
10 COLOR0, COLOR1, COLOR2, COLOR3,
11 COLOR4, COLOR5, COLOR6, COLOR7,
12 COLOR8, COLOR9, COLOR10, COLOR11,
13 COLOR12, COLOR13, COLOR14, COLOR15};
14 static int rows, cols;
15 static int fnrows, fncols;
16 static struct font *fonts[3];
18 int pad_init(void)
20 int r, g, b;
21 if (pad_font(FR, FI, FB))
22 return 1;
23 rows = fb_rows() / fnrows;
24 cols = fb_cols() / fncols;
25 for (r = 0; r < 6; r++) {
26 for (g = 0; g < 6; g++) {
27 for (b = 0; b < 6; b++) {
28 int idx = 16 + r * 36 + g * 6 + b;
29 int rfin = r ? (r * 40 + 55) : 0;
30 int gfin = g ? (g * 40 + 55) : 0;
31 int bfin = b ? (b * 40 + 55) : 0;
32 cd[idx] = (rfin << 16) | (gfin << 8) | (bfin);
36 for (r = 0; r < 24; r++)
37 cd[232 + r] = ((r * 10 + 8) << 16) |
38 ((r * 10 + 8) << 8) | (r * 10 + 8);
39 return 0;
42 void pad_free(void)
44 int i;
45 for (i = 0; i < 3; i++)
46 if (fonts[i])
47 font_free(fonts[i]);
50 #define CR(a) (((a) >> 16) & 0x0000ff)
51 #define CG(a) (((a) >> 8) & 0x0000ff)
52 #define CB(a) ((a) & 0x0000ff)
53 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
55 static unsigned mixed_color(int fg, int bg, unsigned val)
57 unsigned int fore = cd[fg], back = cd[bg];
58 unsigned char r = COLORMERGE(CR(fore), CR(back), val);
59 unsigned char g = COLORMERGE(CG(fore), CG(back), val);
60 unsigned char b = COLORMERGE(CB(fore), CB(back), val);
61 return FB_VAL(r, g, b);
64 static unsigned color2fb(int c)
66 return FB_VAL(CR(cd[c]), CG(cd[c]), CB(cd[c]));
69 /* glyph bitmap cache */
70 #define GCLCNT (1 << 7) /* glyph cache list count */
71 #define GCLLEN (1 << 4) /* glyph cache list length */
72 #define GCIDX(c) ((c) & (GCLCNT - 1))
74 static fbval_t gc_mem[GCLCNT][GCLLEN][NDOTS];
75 static int gc_next[GCLCNT];
76 static struct glyph {
77 int c;
78 short fg, bg;
79 } gc_info[GCLCNT][GCLLEN];
81 static fbval_t *gc_get(int c, short fg, short bg)
83 struct glyph *g = gc_info[GCIDX(c)];
84 int i;
85 for (i = 0; i < GCLLEN; i++)
86 if (g[i].c == c && g[i].fg == fg && g[i].bg == bg)
87 return gc_mem[GCIDX(c)][i];
88 return NULL;
91 static fbval_t *gc_put(int c, short fg, short bg)
93 int idx = GCIDX(c);
94 int pos = gc_next[idx]++;
95 struct glyph *g = &gc_info[idx][pos];
96 if (gc_next[idx] >= GCLLEN)
97 gc_next[idx] = 0;
98 g->c = c;
99 g->fg = fg;
100 g->bg = bg;
101 return gc_mem[idx][pos];
104 static void bmp2fb(fbval_t *d, char *s, int fg, int bg, int nr, int nc)
106 int i, j;
107 for (i = 0; i < fnrows; i++) {
108 for (j = 0; j < fncols; j++) {
109 unsigned v = i < nr && j < nc ?
110 (unsigned char) s[i * nc + j] : 0;
111 d[i * fncols + j] = mixed_color(fg, bg, v);
116 static fbval_t *ch2fb(int fn, int c, short fg, short bg)
118 char bits[NDOTS];
119 fbval_t *fbbits;
120 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
121 return NULL;
122 if ((fbbits = gc_get(c, fg, bg)))
123 return fbbits;
124 if (font_bitmap(fonts[fn], bits, c))
125 return NULL;
126 fbbits = gc_put(c, fg, bg);
127 bmp2fb(fbbits, bits, fg & FN_C, bg & FN_C,
128 font_rows(fonts[fn]), font_cols(fonts[fn]));
129 return fbbits;
132 static void fb_set(int r, int c, void *mem, int len)
134 int bpp = FBM_BPP(fb_mode());
135 if (r < 0 || r >= fb_rows())
136 return;
137 if (c + len >= fb_cols())
138 len = MAX(0, fb_cols() - c);
139 memcpy(fb_mem(r) + c * bpp, mem, len * bpp);
142 static void fb_box(int sr, int er, int sc, int ec, fbval_t val)
144 static fbval_t line[32 * NCOLS];
145 int i;
146 for (i = sc; i < ec; i++)
147 line[i - sc] = val;
148 for (i = sr; i < er; i++)
149 fb_set(i, sc, line, ec - sc);
152 static int fnsel(int fg, int bg)
154 if ((fg | bg) & FN_B)
155 return fonts[2] ? 2 : 0;
156 if ((fg | bg) & FN_I)
157 return fonts[1] ? 1 : 0;
158 return 0;
161 void pad_put(int ch, int r, int c, int fg, int bg)
163 int sr = fnrows * r;
164 int sc = fncols * c;
165 fbval_t *bits;
166 int i;
167 if ((fg & 0xfff8) == FN_B && !fonts[2])
168 fg |= 8; /* increase intensity of no FB */
169 bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
170 if (!bits)
171 bits = ch2fb(0, ch, fg, bg);
172 if (!bits)
173 fb_box(sr, sr + fnrows, sc, sc + fncols, color2fb(bg & FN_C));
174 else
175 for (i = 0; i < fnrows; i++)
176 fb_set(sr + i, sc, bits + (i * fncols), fncols);
179 void pad_fill(int sr, int er, int sc, int ec, int c)
181 int fber = er >= 0 ? er * fnrows : fb_rows();
182 int fbec = ec >= 0 ? ec * fncols : fb_cols();
183 fb_box(sr * fnrows, fber, sc * fncols, fbec, color2fb(c & 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 struct font *r = fr ? font_open(fr) : NULL;
199 if (!r)
200 return 1;
201 if (fonts[0])
202 font_free(fonts[0]);
203 if (fonts[1])
204 font_free(fonts[1]);
205 if (fonts[2])
206 font_free(fonts[2]);
207 fonts[0] = r;
208 fonts[1] = fi ? font_open(fi) : NULL;
209 fonts[2] = fb ? font_open(fb) : NULL;
210 memset(gc_info, 0, sizeof(gc_info));
211 fnrows = font_rows(fonts[0]);
212 fncols = font_cols(fonts[0]);
213 return 0;