Makefile: update object files when conf.h changes
[fbpad.git] / pad.c
blob6db7830369d76c836383bb6888ca6b98be2aee29
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 rows, cols;
10 static int fnrows, fncols;
11 static struct font *fonts[3];
13 int pad_init(void)
15 if (pad_font(FR, FI, FB))
16 return 1;
17 rows = fb_rows() / fnrows;
18 cols = fb_cols() / fncols;
19 return 0;
22 void pad_free(void)
24 int i;
25 for (i = 0; i < 3; i++)
26 if (fonts[i])
27 font_free(fonts[i]);
30 #define CR(a) (((a) >> 16) & 0x0000ff)
31 #define CG(a) (((a) >> 8) & 0x0000ff)
32 #define CB(a) ((a) & 0x0000ff)
33 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
35 static unsigned mixed_color(int fg, int bg, unsigned val)
37 unsigned char r = COLORMERGE(CR(fg), CR(bg), val);
38 unsigned char g = COLORMERGE(CG(fg), CG(bg), val);
39 unsigned char b = COLORMERGE(CB(fg), CB(bg), val);
40 return FB_VAL(r, g, b);
43 static unsigned color2fb(int c)
45 return FB_VAL(CR(c), CG(c), CB(c));
48 /* glyph bitmap cache */
49 #define GCLCNT (1 << 7) /* glyph cache list count */
50 #define GCLLEN (1 << 4) /* glyph cache list length */
51 #define GCIDX(c) ((c) & (GCLCNT - 1))
53 static fbval_t gc_mem[GCLCNT][GCLLEN][NDOTS];
54 static int gc_next[GCLCNT];
55 static struct glyph {
56 int c;
57 int fg, bg;
58 } gc_info[GCLCNT][GCLLEN];
60 static fbval_t *gc_get(int c, int fg, int bg)
62 struct glyph *g = gc_info[GCIDX(c)];
63 int i;
64 for (i = 0; i < GCLLEN; i++)
65 if (g[i].c == c && g[i].fg == fg && g[i].bg == bg)
66 return gc_mem[GCIDX(c)][i];
67 return NULL;
70 static fbval_t *gc_put(int c, int fg, int bg)
72 int idx = GCIDX(c);
73 int pos = gc_next[idx]++;
74 struct glyph *g = &gc_info[idx][pos];
75 if (gc_next[idx] >= GCLLEN)
76 gc_next[idx] = 0;
77 g->c = c;
78 g->fg = fg;
79 g->bg = bg;
80 return gc_mem[idx][pos];
83 static void bmp2fb(fbval_t *d, char *s, int fg, int bg, int nr, int nc)
85 int i, j;
86 for (i = 0; i < fnrows; i++) {
87 for (j = 0; j < fncols; j++) {
88 unsigned v = i < nr && j < nc ?
89 (unsigned char) s[i * nc + j] : 0;
90 d[i * fncols + j] = mixed_color(fg, bg, v);
95 static fbval_t *ch2fb(int fn, int c, int fg, int bg)
97 char bits[NDOTS];
98 fbval_t *fbbits;
99 if (c < 0 || (c < 128 && (!isprint(c) || isspace(c))))
100 return NULL;
101 if ((fbbits = gc_get(c, fg, bg)))
102 return fbbits;
103 if (font_bitmap(fonts[fn], bits, c))
104 return NULL;
105 fbbits = gc_put(c, fg, bg);
106 bmp2fb(fbbits, bits, fg & FN_C, bg & FN_C,
107 font_rows(fonts[fn]), font_cols(fonts[fn]));
108 return fbbits;
111 static void fb_set(int r, int c, void *mem, int len)
113 int bpp = FBM_BPP(fb_mode());
114 memcpy(fb_mem(r) + c * bpp, mem, len * bpp);
117 static void fb_box(int sr, int er, int sc, int ec, fbval_t val)
119 static fbval_t line[32 * NCOLS];
120 int i;
121 for (i = sc; i < ec; i++)
122 line[i - sc] = val;
123 for (i = sr; i < er; i++)
124 fb_set(i, sc, line, ec - sc);
127 static int fnsel(int fg, int bg)
129 if ((fg | bg) & FN_B)
130 return fonts[2] ? 2 : 0;
131 if ((fg | bg) & FN_I)
132 return fonts[1] ? 1 : 0;
133 return 0;
136 void pad_put(int ch, int r, int c, int fg, int bg)
138 int sr = fnrows * r;
139 int sc = fncols * c;
140 fbval_t *bits;
141 int i;
142 bits = ch2fb(fnsel(fg, bg), ch, fg, bg);
143 if (!bits)
144 bits = ch2fb(0, ch, fg, bg);
145 if (!bits)
146 fb_box(sr, sr + fnrows, sc, sc + fncols, color2fb(bg & FN_C));
147 else
148 for (i = 0; i < fnrows; i++)
149 fb_set(sr + i, sc, bits + (i * fncols), fncols);
152 void pad_fill(int sr, int er, int sc, int ec, int c)
154 int fber = er >= 0 ? er * fnrows : fb_rows();
155 int fbec = ec >= 0 ? ec * fncols : fb_cols();
156 fb_box(sr * fnrows, fber, sc * fncols, fbec, color2fb(c & FN_C));
159 int pad_rows(void)
161 return rows;
164 int pad_cols(void)
166 return cols;
169 int pad_font(char *fr, char *fi, char *fb)
171 struct font *r = fr ? font_open(fr) : NULL;
172 if (!r)
173 return 1;
174 fonts[0] = r;
175 fonts[1] = fi ? font_open(fi) : NULL;
176 fonts[2] = fb ? font_open(fb) : NULL;
177 memset(gc_info, 0, sizeof(gc_info));
178 fnrows = font_rows(fonts[0]);
179 fncols = font_cols(fonts[0]);
180 return 0;