#ifndef _SDL_FONT_H_
#define _SDL_FONT_H_
#include<SDL.h>
#include<iostream>
#include<fstream>
#include<string>
#include<cstdarg>
inline int SDL_getRval(int x) {
return (unsigned char) x;
}
inline int SDL_getGval(int x) {
return (unsigned char) (unsigned int) x >> 8;
}
inline int SDL_getBval(int x) {
return ((unsigned char)((x)>>16));
}
inline void SDL_SetPixel(SDL_Surface *surf, int x, int y, Uint32 the_color) {
Uint8 *ubuff8;
Uint16 *ubuff16;
Uint32 *ubuff32;
Uint32 color = the_color;
char c1, c2, c3;
if(SDL_MUSTLOCK(surf)) {
if(SDL_LockSurface(surf) < 0)
return;
}
switch(surf->format->BytesPerPixel)
{
case 1:
ubuff8 = (Uint8*) surf->pixels;
ubuff8 += (y * surf->pitch) + x;
*ubuff8 = (Uint8) color;
break;
case 2:
ubuff8 = (Uint8*) surf->pixels;
ubuff8 += (y * surf->pitch) + (x*2);
ubuff16 = (Uint16*) ubuff8;
*ubuff16 = (Uint16) color;
break;
case 3:
ubuff8 = (Uint8*) surf->pixels;
ubuff8 += (y * surf->pitch) + (x*3);
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
c1 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c3 = (color & 0x0000FF);
} else {
c3 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c1 = (color & 0x0000FF);
}
ubuff8[0] = c3;
ubuff8[1] = c2;
ubuff8[2] = c1;
break;
case 4:
ubuff8 = (Uint8*) surf->pixels;
ubuff8 += (y*surf->pitch) + (x*4);
ubuff32 = (Uint32*)ubuff8;
*ubuff32 = color;
break;
default:
std::cerr << "Error Unknown BitDepth!\n";
}
if(SDL_MUSTLOCK(surf)) {
SDL_UnlockSurface(surf);
}
}
struct SDL_Font {
int mx;
int my;
int tcolor;
struct letter {
int **fnt_ptr;
};
letter letters[128];
};
inline int SDL_GetFX(SDL_Font *m,int x, int nw) {
int xp = int((float)x * float(m->mx) / (float)nw);
return int(xp);
}
inline int SDL_GetFZ(SDL_Font *m, int y, int nh) {
int yp = int((float)y * float(m->my) / (float)nh);
return int(yp);
}
template<class type>
void SDL_zero(type *t) {
memset((void*)t, 0, sizeof(type));
}
void SDL_free_font(struct SDL_Font *m) {
SDL_zero<SDL_Font>(m);
for(int l = 0; l <= 127; l++)
if(m->letters[l].fnt_ptr)
for(int i = 0; i < m->mx; i++)
delete [] m->letters[l].fnt_ptr[i];
m->mx = 0;
m->my = 0;
}
void SDL_init_font(SDL_Font *m, int width, int height, int color) {
SDL_free_font(m);
m->mx = width;
m->my = height;
for(int l = 0; l <= 127; l++) {
m->letters[l].fnt_ptr = new int*[width];
for(int p = 0; p < width; p++) {
m->letters[l].fnt_ptr[p] = new int[height];
}
for(int i = 0; i < width; i++) {
for(int z = 0; z < height; z++) {
m->letters[l].fnt_ptr[i][z] = color;
}
}
}
m->tcolor = 0x0;
}
void SDL_write_font(struct SDL_Font *m, char *font_name) {
std::fstream file;
file.open(font_name, std::ios::binary | std::ios::out);
if(file.is_open()) {
int q = -100;
file.write((char*)&q,sizeof(int));
file.write((char*)&m->mx, sizeof(int));
file.write((char*)&m->my, sizeof(int));
file.write((char*)&m->tcolor,sizeof(int));
for(int l = 0; l < 127; l++)
for(int i = 0; i < m->mx; i++)
for(int z = 0; z < m->my; z++)
file.write((char*)&m->letters[l].fnt_ptr[i][z], sizeof(int));
file.close();
}
}
bool SDL_read_font(struct SDL_Font *m, const char *font_name) {
std::fstream file;
int mx , my;
SDL_free_font(m);
file.open(font_name, std::ios::binary | std::ios::in);
if(file.is_open() && file.good()) {
int q = 0;
file.read((char*)&q,sizeof(int));
if(q == -100) {
file.read((char*)&mx, sizeof(int));
file.read((char*)&my, sizeof(int));
file.read((char*)&m->tcolor, sizeof(int));
m->mx = mx;
m->my = my;
if(mx < 0 || mx < 0 || mx > 250 || my > 250) {
file.close();
SDL_init_font(m,20,25,0x0);
return false;
}
for(int l = 0; l <= 127; l++) {
m->letters[l].fnt_ptr = new int*[mx];
for(int p = 0; p < mx; p++) {
m->letters[l].fnt_ptr[p] = new int[my];
}
for(int i = 0; i < m->mx; i++)
for(int z = 0; z < m->my; z++)
if(!file.eof() && file.good())
file.read((char*)&m->letters[l].fnt_ptr[i][z], sizeof(int));
}
file.close();
return true;
}
else {
SDL_zero<SDL_Font>(m);
SDL_init_font(m,20,25,0x0);
file.close();
return false;
}
}
return true;
}
void SDL_PrintText(SDL_Surface *front, SDL_Font *m, int x, int y,Uint32 color,const char *str, ...) {
int prev_x = x;
int offset_x = prev_x, offset_y = y;
int width = 0, height = 0;
char text[5000];// just enough
va_list list;
va_start(list, str);
vsprintf((char*)text,str,list);
va_end(list);
for(unsigned int p = 0; p < strlen(text); p++) {
if(text[p] == '\n') {
offset_x = prev_x;
offset_y += height;
continue;
}
for(int i = 0; i < m->mx; i++) {
for(int z = 0; z < m->my; z++) {
if(m->letters[text[p]].fnt_ptr[i][z] != m->tcolor) {
SDL_SetPixel(front, offset_x+i, offset_y+z, color);
width=i;
if(height < z)
height=z;
}
}
}
offset_x += width;
}
}
void SDL_PrintTextSized(SDL_Surface *front, SDL_Font *m, int x, int y, int w, int h,Uint32 color, const char *str, ...) {
int prev_x = x;
int offset_x = prev_x, offset_y = y;
int width = 0, height = 0;
char text[5000];// just enough
va_list list;
va_start(list, str);
vsprintf((char*)text,str,list);
va_end(list);
for(unsigned int p = 0; p < strlen(text); p++) {
if(text[p] == '\n') {
offset_x = prev_x;
offset_y += height;
continue;
}
for(int i = 0; i < h; i++) {
for(int z = 0; z < w; z++) {
if(m->letters[text[p]].fnt_ptr[SDL_GetFX(m,i,w)][SDL_GetFZ(m,z,h)] != m->tcolor) {
SDL_SetPixel(front, offset_x+i, offset_y+z, color);
width=i;
if(height < z)
height=z;
}
}
}
offset_x += width;
}
}
class SDL_Text {
public:
SDL_Text(std::string fnt_name) {
loaded = LoadFNT(fnt_name);
}
SDL_Text() {
loaded = false;
SDL_zero(&m);
}
~SDL_Text() {
if(loaded == true) {
SDL_free_font(&m);
}
}
bool LoadFNT(std::string fnt_name) {
return (loaded = SDL_read_font(&m, fnt_name.c_str()));
}
void FreeFNT() {
if(loaded == true) {
SDL_free_font(&m);
}
}
SDL_Font *GetFont() { return &m; }
protected:
SDL_Font m;
bool loaded;
};
#endif