Skip to content

Instantly share code, notes, and snippets.

@viperscape viperscape/font.c
Created Apr 14, 2018

Embed
What would you like to do?
bmfont rendering with sdl
#include "font.h"
#include "../SDL/SDL.h"
#include <stdio.h>
#include <string.h>
struct font font_init (SDL_Renderer* renderer, char *filename) {
char filename_[256] = {'\0'};
strcat(filename_, filename);
strcat(filename_, ".fnt");
struct ch chs[256] = {
0,0,0,0,0,0,0,0
};
struct font font = { 0 , chs, NULL };
FILE *f = fopen(filename_, "r");
if (!f) {
fprintf(stderr, "font load error %s\n", filename_);
exit(1);
}
char line[1024] = {'\0'};
int c;
int i = 0;
int skiplines = 3;
int count = 0;
//int cursor = 0;
while ((c = fgetc(f)) != EOF) {
if (i == 1023) {
fprintf(stderr, "max characters exceeded\n");
i = 0;
continue;
}
if ((c == '\n') || (c == '\r')) {
if (skiplines > 0) skiplines--;
else {
int rc = 0;
if (count < 1) {
rc = sscanf(line, "chars count=%i", &count);
if (rc < 1) fprintf(stderr, "font parse error %s\n", line);
font.count = count;
}
else {
int id, x, y, w, h, xo, yo, xa, p, chl = 0;
rc = sscanf(line, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i page=%i chnl=%i", &id, &x, &y, &w, &h, &xo, &yo, &xa, &p, &chl);
if (rc < 10) fprintf(stderr, "font parse error %s\n", line);
struct ch ch = {id, x, y, w, h, xo, yo, xa};
font.chs[id] = ch;
//cursor++;
}
}
for (i;i>0;--i) line[i] = '\0';
}
else {
line[i] = c;
i++;
}
}
fclose(f);
// load texture
for (int i=0; i<256; ++i) filename_[i] = '\0';
strcat(filename_, filename);
strcat(filename_, ".bmp");
SDL_Surface* surface = NULL;
surface = SDL_LoadBMP(filename_);
if (surface == NULL) {
printf("Could not create surface: %s\n\t%s\n", filename_, SDL_GetError());
}
font.tex = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
surface = NULL;
return(font);
}
void font_render (SDL_Renderer* renderer, struct font *font, int x, int y, char *str) {
int cx = x;
int cy = y; //cursors
char ch;
SDL_Rect src;
SDL_Rect dest;
for(int i = 0; i<strlen(str); ++i) {
ch = str[i];
if (ch == ' ') {
cx += font->chs['j'].xadv; // note: we use static 'j' element
continue;
}
else if (ch == '\t') {
cx += font->chs['j'].xadv * 4; // static 4 space tab size
continue;
}
else if (ch == '\n') {
cx = x;
cy += font->chs['j'].h + 2;
continue;
}
src.x = font->chs[ch].x;
src.y = font->chs[ch].y;
src.w = font->chs[ch].w;
src.h = font->chs[ch].h;
dest.x = cx + font->chs[ch].xoff;
dest.y = cy + font->chs[ch].yoff;
dest.w = font->chs[ch].w;
dest.h = font->chs[ch].h;
cx += font->chs[ch].xadv;
SDL_RenderCopy(renderer, font->tex, &src, &dest);
}
}
#ifndef FONT_H
#define FONT_H
#include "../SDL/SDL.h"
struct ch {
char id;
int x, y;
int w, h;
int xoff, yoff;
int xadv;
};
struct font {
int count;
struct ch chs[256];
SDL_Texture *tex;
};
extern struct font font_init (SDL_Renderer* renderer, char *filename);
extern void font_render (SDL_Renderer* renderer, struct font *font, int x, int y, char *str);
#endif
#include "font.h"
#include "../SDL/SDL.h"
int main () {
SDL_Renderer* renderer;
// setup your SDL context called 'renderer'
font = font_init(renderer, "assets/fonts/myfont");
font_render(renderer, &font, 50, 50, "hello world\nfont testing\ttesting!");
}
// bmfont: http://www.angelcode.com/products/bmfont/
@viperscape

This comment has been minimized.

Copy link
Owner Author

commented Apr 14, 2018

From BMFont export without Kerning pairs, open TGA (in Photoshop) and convert to RGB, on channels duplicate and name as Alpha 1, save as bitmap with alpha at 32 bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.