2017-12-20 03:50:50 +00:00
|
|
|
/*
|
|
|
|
* vm_bitfont.c
|
2018-02-13 03:15:20 +00:00
|
|
|
*
|
|
|
|
* The bitfont code allows us to define and work with a bitmapped font.
|
|
|
|
* You can find the bitmap font glyphs in the `/fonts` subdir within the
|
|
|
|
* repository root, as well as bmp files that are compiled from those
|
|
|
|
* glyphs (via `/tools/build-fonts`).
|
|
|
|
*
|
|
|
|
* We do not have support for truetype fonts (nor other types of fonts)
|
|
|
|
* at this time, but the glyph system is pretty easy to work with, even
|
|
|
|
* if it is a hack.
|
2017-12-20 03:50:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "vm_bitfont.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new bitfont from a given font name. This font name must
|
|
|
|
* indicate something that exists in the filesystem relative to a point,
|
|
|
|
* which means it must have been created during installation.
|
|
|
|
*
|
|
|
|
* This also indicates what the width and height of each glyph will be,
|
|
|
|
* along with a character mask we will apply when figuring out where to
|
|
|
|
* access bitmap data. (For example, if we only support 7-bit
|
|
|
|
* characters, the cmask should limit us to 0-127 so that we can't
|
|
|
|
* accidentally pass in a value that uses the 8th bit and crashes us
|
|
|
|
* out.
|
|
|
|
*/
|
|
|
|
vm_bitfont *
|
|
|
|
vm_bitfont_create(vm_screen *screen,
|
2018-01-04 03:50:30 +00:00
|
|
|
const vm_8bit *fontdata, int fontsize,
|
|
|
|
int width, int height, char cmask)
|
2017-12-20 03:50:50 +00:00
|
|
|
{
|
|
|
|
SDL_Surface *surf;
|
2018-01-04 03:50:30 +00:00
|
|
|
SDL_RWops *rw;
|
2017-12-20 03:50:50 +00:00
|
|
|
vm_bitfont *font;
|
2018-01-04 03:50:30 +00:00
|
|
|
|
2018-01-04 20:21:05 +00:00
|
|
|
// Build the RWops object from the given fontdata; we have to use
|
|
|
|
// FromConstMem because we passed a const pointer into this
|
|
|
|
// function.
|
2018-01-04 03:50:30 +00:00
|
|
|
rw = SDL_RWFromConstMem(fontdata, fontsize);
|
|
|
|
if (rw == NULL) {
|
2018-03-30 02:45:25 +00:00
|
|
|
log_crit("Failed to create RWops from font data: %s",
|
2018-01-04 03:50:30 +00:00
|
|
|
SDL_GetError());
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-01-04 20:21:05 +00:00
|
|
|
// And here we build a surface from the RWops, which is a nifty way
|
|
|
|
// of getting a bitmap from memory rather than loading from a file.
|
2018-01-04 03:50:30 +00:00
|
|
|
surf = SDL_LoadBMP_RW(rw, 0);
|
|
|
|
if (surf == NULL) {
|
2018-03-30 02:45:25 +00:00
|
|
|
log_crit("Failed to create bitmap from RWops: %s",
|
2018-01-04 03:50:30 +00:00
|
|
|
SDL_GetError());
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-12-20 03:50:50 +00:00
|
|
|
|
|
|
|
font = malloc(sizeof(vm_bitfont));
|
|
|
|
if (font == NULL) {
|
2018-03-30 02:45:25 +00:00
|
|
|
log_crit("Could not allocate memory for font");
|
2017-12-20 03:50:50 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-01-04 20:21:05 +00:00
|
|
|
// The texture is what we can use to blit onto the renderer
|
2017-12-20 03:50:50 +00:00
|
|
|
font->texture = SDL_CreateTextureFromSurface(screen->render, surf);
|
2018-01-04 20:21:05 +00:00
|
|
|
|
2017-12-20 03:50:50 +00:00
|
|
|
font->width = width;
|
|
|
|
font->height = height;
|
|
|
|
font->cmask = cmask;
|
|
|
|
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This just frees the memory for the font.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
vm_bitfont_free(vm_bitfont *font)
|
|
|
|
{
|
|
|
|
SDL_DestroyTexture(font->texture);
|
|
|
|
free(font);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function will provide the correct offset within the bitmap data
|
|
|
|
* where you can find the glyph that matches the given character.
|
|
|
|
* Because we want to note both an x and a y coordinate, we require
|
|
|
|
* pointers to those, which we simply dereference to assign the right
|
|
|
|
* value.
|
|
|
|
*/
|
|
|
|
void
|
2017-12-27 22:47:26 +00:00
|
|
|
vm_bitfont_offset(vm_bitfont *font, char ch, vm_area *area)
|
2017-12-20 03:50:50 +00:00
|
|
|
{
|
|
|
|
int row = (ch & 0xf0) >> 4;
|
|
|
|
int col = ch & 0x0f;
|
|
|
|
|
2017-12-27 22:47:26 +00:00
|
|
|
area->xoff = col * font->width;
|
|
|
|
area->yoff = row * font->height;
|
2017-12-20 03:50:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Render the given character, in the given font, on the given screen at
|
|
|
|
* the given destination.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
vm_bitfont_render(vm_bitfont *font,
|
|
|
|
vm_screen *screen,
|
2017-12-27 22:31:02 +00:00
|
|
|
vm_area *dest,
|
2017-12-20 03:50:50 +00:00
|
|
|
char ch)
|
|
|
|
{
|
2017-12-27 22:47:26 +00:00
|
|
|
vm_area src;
|
2017-12-20 03:50:50 +00:00
|
|
|
|
|
|
|
// Our bitmap font may not be able to support all 256 possible
|
|
|
|
// values that a character can hold; the cmask will limit us to
|
|
|
|
// what's safe to query in the bitmap.
|
|
|
|
ch = ch & font->cmask;
|
|
|
|
|
|
|
|
// The width and height of the glyph are as indicated by the font
|
|
|
|
// struct
|
2017-12-27 22:47:26 +00:00
|
|
|
src.width = font->width;
|
|
|
|
src.height = font->height;
|
2017-12-22 18:56:22 +00:00
|
|
|
|
2017-12-20 03:50:50 +00:00
|
|
|
// Get the spot in the bitmap where the glyph is found
|
2017-12-27 22:47:26 +00:00
|
|
|
vm_bitfont_offset(font, ch, &src);
|
2017-12-20 03:50:50 +00:00
|
|
|
|
2017-12-27 22:47:26 +00:00
|
|
|
// Bring the destination attributes into the SDL_Rect we need to
|
|
|
|
// pass into SDL_RenderCopy(). Also bring in the src attributes
|
|
|
|
// we've built earlier.
|
|
|
|
MAKE_SDL_RECT(dest_rect, *dest);
|
|
|
|
MAKE_SDL_RECT(src_rect, src);
|
2017-12-22 18:56:22 +00:00
|
|
|
|
2018-01-23 22:09:27 +00:00
|
|
|
if (screen->render) {
|
|
|
|
if (SDL_RenderCopy(screen->render, font->texture,
|
|
|
|
&src_rect, &dest_rect) < 0
|
|
|
|
) {
|
2018-03-30 02:45:25 +00:00
|
|
|
log_crit("Failed to render glyph: %s", SDL_GetError());
|
2018-01-23 22:09:27 +00:00
|
|
|
return ERR_GFXOP;
|
|
|
|
}
|
2017-12-20 03:50:50 +00:00
|
|
|
}
|
|
|
|
|
2018-01-23 20:52:16 +00:00
|
|
|
screen->dirty = true;
|
2017-12-20 03:50:50 +00:00
|
|
|
return OK;
|
|
|
|
}
|