fbpad: split the screen at row and column boundaries
[fbpad.git] / pad.c
blobe10328529cd06bd4cd1eaf3f49006e01ac9b8cca
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "conf.h"
6 #include "draw.h"
7 #include "fbpad.h"
9 static int fbroff, fbcoff, fbrows, fbcols;
10 static int rows, cols;
11 static int fnrows, fncols;
12 static int bpp;
13 static struct font *fonts[3];
15 int pad_init(void)
17 if (pad_font(FR, FI, FB))
18 return 1;
19 rows = fb_rows() / fnrows;
20 cols = fb_cols() / fncols;
21 bpp = FBM_BPP(fb_mode());
22 pad_conf(0, 0, fb_rows(), fb_cols());
23 return 0;
26 void pad_conf(int roff, int coff, int _rows, int _cols)
28 fbroff = roff;
29 fbcoff = coff;
30 fbrows = _rows;
31 fbcols = _cols;
32 rows = fbrows / fnrows;
33 cols = fbcols / fncols;
36 void pad_free(void)
38 int i;
39 for (i = 0; i < 3; i++)
40 if (fonts[i])
41 font_free(fonts[i]);
44 #define CR(a) (((a) >> 16) & 0x0000ff)
45 #define CG(a) (((a) >> 8) & 0x0000ff)
46 #define CB(a) ((a) & 0x0000ff)
47 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
49 static unsigned mixed_color(int fg, int bg, unsigned val)
51 unsigned char r = COLORMERGE(CR(fg), CR(bg), val);
52 unsigned char g = COLORMERGE(CG(fg), CG(bg), val);
53 unsigned char b = COLORMERGE(CB(fg), CB(bg), val);
54 return FB_VAL(r, g, b);
57 static unsigned color2fb(int c)
59 return FB_VAL(CR(c), CG(c), CB(c));
62 /* glyph bitmap cache */
63 #define GCLCNT (1 << 7) /* glyph cache list count */
64 #define GCLLEN (1 << 4) /* glyph cache list length */
65 #define GCIDX(c) ((c) & (GCLCNT - 1))
67 static char gc_mem[GCLCNT][GCLLEN][NDOTS * 4];
68 static int gc_next[GCLCNT];
69 static struct glyph {
70 int c;
71 int fg, bg;
72 } gc_info[GCLCNT][GCLLEN];
74 static char *gc_get(int c, int fg, int bg)
76 struct glyph *g = gc_info[GCIDX(c)];
77 int i;
78 for (i = 0; i < GCLLEN; i++)
79 if (g[i].c == c && g[i].fg == fg && g[i].bg == bg)
80 return gc_mem[GCIDX(c)][i];
81 return NULL;
84 static char *gc_put(int c, int fg, int bg)
86 int idx = GCIDX(c);
87 int pos = gc_next[idx]++;
88 struct glyph *g = &gc_info[idx][pos];
89 if (gc_next[idx] >= GCLLEN)
90 gc_next[idx] = 0;
91 g->c = c;
92 g->fg = fg;
93 g->bg = bg;
94 return gc_mem[idx][pos];
97 static void bmp2fb(char *d, char *s, int fg, int bg, int nr, int nc)
99 int i, j, k;
100 for (i = 0; i < fnrows; i++) {
101 char *p = d + i * fncols * bpp;
102 for (j = 0; j < fncols; j++) {
103 unsigned v = i < nr && j < nc ?
104 (unsigned char) s[i * nc + j] : 0;
105 unsigned c = mixed_color(fg, bg, v);
106 for (k = 0; k < bpp; k++) /* little-endian */
107 *p++ = (c >> (k * 8)) & 0xff;
112 static char *ch2fb(int fn, int c, int fg, int bg)
114 char bits[NDOTS * 4];
115 char *fbbits;
116 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
117 return NULL;
118 if ((fbbits = gc_get(c, fg, bg)))
119 return fbbits;
120 if (font_bitmap(fonts[fn], bits, c))
121 return NULL;
122 fbbits = gc_put(c, fg, bg);
123 bmp2fb(fbbits, bits, fg & FN_C, bg & FN_C,
124 font_rows(fonts[fn]), font_cols(fonts[fn]));
125 return fbbits;
128 static void fb_set(int r, int c, void *mem, int len)
130 memcpy(fb_mem(fbroff + r) + (fbcoff + c) * bpp, mem, len * bpp);
133 static char *rowbuf(unsigned c, int len)
135 static char row[32 * NCOLS];
136 char *p = row;
137 int i, k;
138 for (i = 0; i < len; i++)
139 for (k = 0; k < bpp; k++) /* little-endian */
140 *p++ = (c >> (k * 8)) & 0xff;
141 return row;
144 static void fb_box(int sr, int er, int sc, int ec, unsigned val)
146 char *row = rowbuf(val, ec - sc);
147 int i;
148 for (i = sr; i < er; i++)
149 fb_set(i, sc, row, ec - sc);
152 void pad_border(unsigned c, int wid)
154 int v = color2fb(c & FN_C);
155 if (fbroff < wid || fbcoff < wid)
156 return;
157 fb_box(-wid, 0, -wid, fbcols + wid, v);
158 fb_box(fbrows, fbrows + wid, -wid, fbcols + wid, v);
159 fb_box(-wid, fbrows + wid, -wid, 0, v);
160 fb_box(-wid, fbrows + wid, fbcols, fbcols + wid, v);
163 static int fnsel(int fg, int bg)
165 if ((fg | bg) & FN_B)
166 return fonts[2] ? 2 : 0;
167 if ((fg | bg) & FN_I)
168 return fonts[1] ? 1 : 0;
169 return 0;
172 void pad_put(int ch, int r, int c, int fg, int bg)
174 int sr = fnrows * r;
175 int sc = fncols * c;
176 char *bits;
177 int i;
178 bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
179 if (!bits)
180 bits = ch2fb(0, ch, fg, bg);
181 if (!bits)
182 fb_box(sr, sr + fnrows, sc, sc + fncols, color2fb(bg & FN_C));
183 else
184 for (i = 0; i < fnrows; i++)
185 fb_set(sr + i, sc, bits + (i * fncols * bpp), fncols);
188 void pad_fill(int sr, int er, int sc, int ec, int c)
190 int fber = er >= 0 ? er * fnrows : fbrows;
191 int fbec = ec >= 0 ? ec * fncols : fbcols;
192 fb_box(sr * fnrows, fber, sc * fncols, fbec, color2fb(c & FN_C));
195 int pad_rows(void)
197 return rows;
200 int pad_cols(void)
202 return cols;
205 int pad_font(char *fr, char *fi, char *fb)
207 struct font *r = fr ? font_open(fr) : NULL;
208 if (!r)
209 return 1;
210 fonts[0] = r;
211 fonts[1] = fi ? font_open(fi) : NULL;
212 fonts[2] = fb ? font_open(fb) : NULL;
213 memset(gc_info, 0, sizeof(gc_info));
214 fnrows = font_rows(fonts[0]);
215 fncols = font_cols(fonts[0]);
216 return 0;
219 char *pad_fbdev(void)
221 static char fbdev[1024];
222 snprintf(fbdev, sizeof(fbdev), "FBDEV=%s:%dx%d%+d%+d",
223 fb_dev(), fbcols, fbrows, fbcoff, fbroff);
224 return fbdev;
227 /* character height */
228 int pad_crows(void)
230 return fnrows;
233 /* character width */
234 int pad_ccols(void)
236 return fncols;