11 #define NCACHE (1 << 11)
12 #define MAXFBWIDTH (1 << 12)
14 static unsigned int cd
[] = {
15 COLOR0
, COLOR1
, COLOR2
, COLOR3
,
16 COLOR4
, COLOR5
, COLOR6
, COLOR7
,
17 COLOR8
, COLOR9
, COLOR10
, COLOR11
,
18 COLOR12
, COLOR13
, COLOR14
, COLOR15
};
19 static int rows
, cols
;
20 static int fnrows
, fncols
;
21 static struct font
*fonts
[32];
25 static int fnsets
[16][3];
26 static char *fnpaths
[][3] = {F0
, F1
, F2
, F3
, F4
};
28 static int fontadd(char *path
)
30 fonts
[nfonts
] = font_open(path
);
32 fprintf(stderr
, "pad: bad font <%s>\n", path
);
43 if (sizeof(fbval_t
) != FBM_BPP(fb_mode())) {
44 fprintf(stderr
, "pad_init: fbval_t doesn't match fb depth\n");
47 for (i
= 0; i
< ARRAY_SIZE(fnpaths
); i
++) {
48 for (j
= 0; j
< 3; j
++) {
51 if ((fn
= fontadd(fnpaths
[i
][j
])) < 0)
67 for (i
= 0; i
< nfonts
; i
++)
72 #define CR(a) (((a) >> 16) & 0x0000ff)
73 #define CG(a) (((a) >> 8) & 0x0000ff)
74 #define CB(a) ((a) & 0x0000ff)
75 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
77 static unsigned mixed_color(int fg
, int bg
, unsigned val
)
79 unsigned int fore
= cd
[fg
], back
= cd
[bg
];
80 unsigned char r
= COLORMERGE(CR(fore
), CR(back
), val
);
81 unsigned char g
= COLORMERGE(CG(fore
), CG(back
), val
);
82 unsigned char b
= COLORMERGE(CB(fore
), CB(back
), val
);
83 return FB_VAL(r
, g
, b
);
86 static unsigned color2fb(int c
)
88 return FB_VAL(CR(cd
[c
]), CG(cd
[c
]), CB(cd
[c
]));
91 static fbval_t cache
[NCACHE
][MAXDOTS
];
98 static struct glyph
*glyph_entry(int c
, int fn
, int fg
, int bg
)
100 return &glyphs
[((c
- 32) ^ (fg
<< 6) ^ (bg
<< 5) ^ (fn
<< 8)) & (NCACHE
- 1)];
103 static fbval_t
*glyph_cache(int c
, int fn
, short fg
, short bg
)
105 struct glyph
*g
= glyph_entry(c
, fn
, fg
, bg
);
106 if (g
->c
== c
&& g
->fn
== fn
&& g
->fg
== fg
&& g
->bg
== bg
)
107 return cache
[g
- glyphs
];
111 static fbval_t
*glyph_add(int c
, int fn
, short fg
, short bg
)
113 struct glyph
*g
= glyph_entry(c
, fn
, fg
, bg
);
118 return cache
[g
- glyphs
];
121 static void bmp2fb(fbval_t
*d
, char *s
, int fg
, int bg
, int nr
, int nc
)
124 for (i
= 0; i
< fnrows
; i
++) {
125 for (j
= 0; j
< fncols
; j
++) {
126 unsigned v
= i
< nr
&& j
< nc
?
127 (unsigned char) s
[i
* nc
+ j
] : 0;
128 d
[i
* fncols
+ j
] = mixed_color(fg
, bg
, v
);
133 static fbval_t
*ch2fb(int fn
, int c
, short fg
, short bg
)
137 if (c
< 0 || (c
< 256 && (!isprint(c
) || isspace(c
))))
139 if ((fbbits
= glyph_cache(c
, fn
, fg
, bg
)))
141 if (font_bitmap(fonts
[fn
], bits
, c
))
143 fbbits
= glyph_add(c
, fn
, fg
, bg
);
144 bmp2fb(fbbits
, bits
, FN_C(fg
), FN_C(bg
),
145 font_rows(fonts
[fn
]), font_cols(fonts
[fn
]));
149 static void fb_box(int sr
, int sc
, int er
, int ec
, fbval_t val
)
151 static fbval_t line
[MAXFBWIDTH
];
154 for (i
= 0; i
< cn
; i
++)
156 for (i
= sr
; i
< er
; i
++)
157 fb_set(i
, sc
, line
, cn
);
160 static int fnsel(int fg
, int bg
)
162 if ((fg
| bg
) & FN_B
)
163 return fnsets
[font
][2];
164 if ((fg
| bg
) & FN_I
)
165 return fnsets
[font
][1];
166 return fnsets
[font
][0];
169 void pad_put(int ch
, int r
, int c
, int fg
, int bg
)
174 fbval_t
*bits
= ch2fb(fnsel(fg
, bg
), ch
, fg
, bg
);
176 bits
= ch2fb(0, ch
, fg
, bg
);
178 fb_box(sr
, sc
, sr
+ fnrows
, sc
+ fncols
, color2fb(FN_C(bg
)));
180 for (i
= 0; i
< fnrows
; i
++)
181 fb_set(sr
+ i
, sc
, bits
+ (i
* fncols
), fncols
);
184 void pad_blank(int c
)
186 fb_box(0, 0, fb_rows(), fb_cols(), color2fb(FN_C(c
)));
189 void pad_blankrow(int r
, int bg
)
192 int er
= r
== rows
- 1 ? fb_rows() : (r
+ 1) * fnrows
;
193 fb_box(sr
, 0, er
, fb_cols(), color2fb(FN_C(bg
)));
208 font
= i
< ARRAY_SIZE(fnpaths
) ? i
: 0;
209 fnrows
= font_rows(fonts
[fnsets
[0][0]]);
210 fncols
= font_cols(fonts
[fnsets
[0][0]]);
211 rows
= fb_rows() / fnrows
;
212 cols
= fb_cols() / fncols
;