9 static int fbroff
, fbcoff
, fbrows
, fbcols
;
10 static int rows
, cols
;
11 static int fnrows
, fncols
;
13 static struct font
*fonts
[3];
15 static int gc_init(void);
16 static void gc_free(void);
17 static void gc_refresh(void);
21 if (pad_font(FR
, FI
, FB
))
23 fnrows
= font_rows(fonts
[0]);
24 fncols
= font_cols(fonts
[0]);
27 rows
= fb_rows() / fnrows
;
28 cols
= fb_cols() / fncols
;
29 bpp
= FBM_BPP(fb_mode());
30 pad_conf(0, 0, fb_rows(), fb_cols());
34 void pad_conf(int roff
, int coff
, int _rows
, int _cols
)
40 rows
= fbrows
/ fnrows
;
41 cols
= fbcols
/ fncols
;
52 #define CR(a) (((a) >> 16) & 0x0000ff)
53 #define CG(a) (((a) >> 8) & 0x0000ff)
54 #define CB(a) ((a) & 0x0000ff)
55 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
57 static unsigned mixed_color(int fg
, int bg
, unsigned val
)
59 unsigned char r
= COLORMERGE(CR(fg
), CR(bg
), val
);
60 unsigned char g
= COLORMERGE(CG(fg
), CG(bg
), val
);
61 unsigned char b
= COLORMERGE(CB(fg
), CB(bg
), val
);
62 return FB_VAL(r
, g
, b
);
65 static unsigned color2fb(int c
)
67 return FB_VAL(CR(c
), CG(c
), CB(c
));
70 /* glyph bitmap cache: use CGLCNT lists of size CGLLEN each */
71 #define GCLCNT (1 << 7) /* glyph cache list count */
72 #define GCLLEN (1 << 4) /* glyph cache list length */
73 #define GCGLEN (fnrows * fncols * 4) /* bytes to store a glyph */
74 #define GCN (GCLCNT * GCLLEN) /* total glpyhs */
75 #define GCIDX(c) ((c) & (GCLCNT - 1))
77 static char *gc_mem
; /* cached glyph's memory */
78 static int gc_next
[GCLCNT
]; /* the next slot to use in each list */
79 static int gc_glyph
[GCN
]; /* cached glyphs */
80 static int gc_bg
[GCN
];
81 static int gc_fg
[GCN
];
83 static int gc_init(void)
85 gc_mem
= malloc(GCLCNT
* GCLLEN
* GCGLEN
);
89 static void gc_free(void)
94 static char *gc_get(int c
, int fg
, int bg
)
96 int idx
= GCIDX(c
) * GCLLEN
;
98 for (i
= idx
; i
< idx
+ GCLLEN
; i
++)
99 if (gc_glyph
[i
] == c
&& gc_fg
[i
] == fg
&& gc_bg
[i
] == bg
)
100 return gc_mem
+ i
* GCGLEN
;
104 static char *gc_put(int c
, int fg
, int bg
)
107 int pos
= gc_next
[lst
]++;
108 int idx
= lst
* GCLLEN
+ pos
;
109 if (gc_next
[lst
] >= GCLLEN
)
114 return gc_mem
+ idx
* GCGLEN
;
117 static void gc_refresh(void)
119 memset(gc_next
, 0, sizeof(gc_next
));
120 memset(gc_glyph
, 0, sizeof(gc_glyph
));
123 static void bmp2fb(char *d
, char *s
, int fg
, int bg
, int nr
, int nc
)
126 for (i
= 0; i
< fnrows
; i
++) {
127 char *p
= d
+ i
* fncols
* bpp
;
128 for (j
= 0; j
< fncols
; j
++) {
129 unsigned v
= i
< nr
&& j
< nc
?
130 (unsigned char) s
[i
* nc
+ j
] : 0;
131 unsigned c
= mixed_color(fg
, bg
, v
);
132 for (k
= 0; k
< bpp
; k
++) /* little-endian */
133 *p
++ = (c
>> (k
<< 3)) & 0xff;
138 static char *ch2fb(int fn
, int c
, int fg
, int bg
)
140 static char bits
[1024 * 4];
142 if (c
< 0 || (c
< 128 && (!isprint(c
) || isspace(c
))))
144 if ((fbbits
= gc_get(c
, fg
, bg
)))
146 if (font_bitmap(fonts
[fn
], bits
, c
))
148 fbbits
= gc_put(c
, fg
, bg
);
149 bmp2fb(fbbits
, bits
, fg
& FN_C
, bg
& FN_C
,
150 font_rows(fonts
[fn
]), font_cols(fonts
[fn
]));
154 static void fb_set(int r
, int c
, void *mem
, int len
)
156 memcpy(fb_mem(fbroff
+ r
) + (fbcoff
+ c
) * bpp
, mem
, len
* bpp
);
159 static char *rowbuf(unsigned c
, int len
)
161 static char row
[32 * 1024];
164 for (i
= 0; i
< len
; i
++)
165 for (k
= 0; k
< bpp
; k
++) /* little-endian */
166 *p
++ = (c
>> (k
* 8)) & 0xff;
170 static void fb_box(int sr
, int er
, int sc
, int ec
, unsigned val
)
172 char *row
= rowbuf(val
, ec
- sc
);
174 for (i
= sr
; i
< er
; i
++)
175 fb_set(i
, sc
, row
, ec
- sc
);
178 void pad_border(unsigned c
, int wid
)
180 int v
= color2fb(c
& FN_C
);
181 if (fbroff
< wid
|| fbcoff
< wid
)
183 fb_box(-wid
, 0, -wid
, fbcols
+ wid
, v
);
184 fb_box(fbrows
, fbrows
+ wid
, -wid
, fbcols
+ wid
, v
);
185 fb_box(-wid
, fbrows
+ wid
, -wid
, 0, v
);
186 fb_box(-wid
, fbrows
+ wid
, fbcols
, fbcols
+ wid
, v
);
189 static int fnsel(int fg
, int bg
)
191 if ((fg
| bg
) & FN_B
)
192 return fonts
[2] ? 2 : 0;
193 if ((fg
| bg
) & FN_I
)
194 return fonts
[1] ? 1 : 0;
198 void pad_put(int ch
, int r
, int c
, int fg
, int bg
)
204 bits
= ch2fb(fnsel(fg
, bg
), ch
, fg
, bg
);
206 bits
= ch2fb(0, ch
, fg
, bg
);
208 fb_box(sr
, sr
+ fnrows
, sc
, sc
+ fncols
, color2fb(bg
& FN_C
));
210 for (i
= 0; i
< fnrows
; i
++)
211 fb_set(sr
+ i
, sc
, bits
+ (i
* fncols
* bpp
), fncols
);
214 void pad_fill(int sr
, int er
, int sc
, int ec
, int c
)
216 int fber
= er
>= 0 ? er
* fnrows
: fbrows
;
217 int fbec
= ec
>= 0 ? ec
* fncols
: fbcols
;
218 fb_box(sr
* fnrows
, fber
, sc
* fncols
, fbec
, color2fb(c
& FN_C
));
231 int pad_font(char *fr
, char *fi
, char *fb
)
233 struct font
*r
= fr
? font_open(fr
) : NULL
;
240 fonts
[1] = fi
? font_open(fi
) : NULL
;
241 fonts
[2] = fb
? font_open(fb
) : NULL
;
246 char *pad_fbdev(void)
248 static char fbdev
[1024];
249 snprintf(fbdev
, sizeof(fbdev
), "FBDEV=%s:%dx%d%+d%+d",
250 fb_dev(), fbcols
, fbrows
, fbcoff
, fbroff
);
254 /* character height */
260 /* character width */