VGA Fonts: Difference between revisions

Jump to navigation Jump to search
Added optimised character drawing example
[unchecked revision][unchecked revision]
(→‎Get the copy stored in the VGA BIOS: That must have been an accident.)
(Added optimised character drawing example)
Line 146:
</source>
As you can see, we have only foreground color this time, and the putpixel call has a condition: only invoked if the according bit in the bitmap is set.
 
Of course the code above will be excruciatingly slow (mostly due to doing one pixel at a time, and repeatedly recalculating the address for each pixel within the "putpixel()" function). For much better performance, the code above can be optimised to use boolean operations and a "mask lookup table" instead. For example (for an 8-bpp mode):
 
<source lang="c">
//this is the bitmap font you've loaded
unsigned char *font;
 
void drawchar_8BPP(unsigned char c, int x, int y, int fgcolor, int bgcolor)
{
void *dest;
uint32_t *dest32;
unsigned char *src;
int row;
uint32_t fgcolor32;
uint32_t bgcolor32;
 
fgcolor32 = fgcolor | (fgcolor << 8) | (fgcolor << 16) | (fgcolor << 24);
bgcolor32 = bgcolor | (bgcolor << 8) | (bgcolor << 16) | (bgcolor << 24);
src = font + c * 16;
dest = videoBuffer + y * bytes_per_line + x;
for(row = 0; row < 16; row++) {
if(*src != 0) {
mask_low = mask_table[*src][0];
mask_high = mask_table[*src][1];
dest32 = dest;
dest32[0] = (bgcolor32 & !mask_low) | (fgcolor32 & mask_low);
dest32[1] = (bgcolor32 & !mask_high) | (fgcolor32 & mask_high);
}
src++;
dest += bytes_per_line;
}
}
 
 
void drawchar_transparent_8BPP(unsigned char c, int x, int y, int fgcolor)
{
void *dest;
uint32_t *dest32;
unsigned char *src;
int row;
uint32_t fgcolor32;
 
fgcolor32 = fgcolor | (fgcolor << 8) | (fgcolor << 16) | (fgcolor << 24);
src = font + c * 16;
dest = videoBuffer + y * bytes_per_line + x;
for(row = 0; row < 16; row++) {
if(*src != 0) {
mask_low = mask_table[*src][0];
mask_high = mask_table[*src][1];
dest32 = dest;
dest32[0] = (dest[0] & !mask_low) | (fgcolor32 & mask_low);
dest32[1] = (dest[1] & !mask_high) | (fgcolor32 & mask_high);
}
src++;
dest += bytes_per_line;
}
}
</source>
 
In this case the address in display memory is only calculated once (rather than up to 128 times) and 8 pixels are done in parallel (which removes the inner loop completely).
 
The main downside for this approach is that you need a different function for each "bits per pixel", except that 15-bpp and 16-bpp can use the same code. For worst case (32-bpp) the lookup table costs 8 KiB. The lookup table for 32-bpp can be re-used for 24-bpp, and for 4-bpp no lookup table is needed at all. To support all standard bit depths that VBE is capable of; this gives a total of 5 versions of each "draw character" function (4-bpp, 8-bpp, 15-bpp and 16-bpp, 24-bpp, 32-bpp) and 3 lookup tables (8-bpp, 15-bpp and 16-bpp, 24-bpp and 32-bpp) which cost a combined total of 14 KiB of data if you use static tables (rather than dynamically generating the desired lookup table if/when needed).
 
 
 
== See Also ==
250

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu