diff --git a/source/code/Libs/NFont.cpp b/source/code/Libs/NFont.cpp deleted file mode 100644 index 7449efc..0000000 --- a/source/code/Libs/NFont.cpp +++ /dev/null @@ -1,1076 +0,0 @@ -/* -NFont: A font class for SDL and SDL_Renderer -by Jonathan Dearborn - -See NFont.h for license info. -*/ - -#include "NFont.h" -#include "SDL_FontCache.h" - -#include -#include -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif - -#include -#include -#include -using std::string; -using std::list; - -#ifdef NFONT_USE_SDL_GPU -#define NFont_Target GPU_Target -#define NFont_Image GPU_Image -#define NFont_Log GPU_LogError -#else -#define NFont_Target SDL_Renderer -#define NFont_Image SDL_Texture -#define NFont_Log SDL_Log -#endif - -#define MIN(a,b) ((a) < (b)? (a) : (b)) -#define MAX(a,b) ((a) > (b)? (a) : (b)) - -#define NFONT_BUFFER_SIZE 1024 - -// vsnprintf replacement adapted from Valentin Milea: -// http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#define vsnprintf c99_vsnprintf - -static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -#endif - - - -static inline SDL_Surface* createSurface24(Uint32 width, Uint32 height) -{ - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0xFF0000, 0x00FF00, 0x0000FF, 0); - #else - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0); - #endif -} - -static inline SDL_Surface* createSurface32(Uint32 width, Uint32 height) -{ - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); - #else - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); - #endif -} - -static inline char* copyString(const char* c) -{ - if(c == NULL) - return NULL; - - char* result = new char[strlen(c)+1]; - strcpy(result, c); - - return result; -} - -static inline Uint32 getPixel(SDL_Surface *Surface, int x, int y) -{ - Uint8* bits; - Uint32 bpp; - - if(x < 0 || x >= Surface->w) - return 0; // Best I could do for errors - - bpp = Surface->format->BytesPerPixel; - bits = ((Uint8*)Surface->pixels) + y*Surface->pitch + x*bpp; - - switch (bpp) - { - case 1: - return *((Uint8*)Surface->pixels + y * Surface->pitch + x); - break; - case 2: - return *((Uint16*)Surface->pixels + y * Surface->pitch/2 + x); - break; - case 3: - // Endian-correct, but slower - Uint8 r, g, b; - r = *((bits)+Surface->format->Rshift/8); - g = *((bits)+Surface->format->Gshift/8); - b = *((bits)+Surface->format->Bshift/8); - return SDL_MapRGB(Surface->format, r, g, b); - break; - case 4: - return *((Uint32*)Surface->pixels + y * Surface->pitch/4 + x); - break; - } - - return 0; // FIXME: Handle errors better -} - -static inline void setPixel(SDL_Surface* surface, int x, int y, Uint32 color) -{ - int bpp = surface->format->BytesPerPixel; - Uint8* bits = ((Uint8 *)surface->pixels) + y*surface->pitch + x*bpp; - - /* Set the pixel */ - switch(bpp) - { - case 1: - *((Uint8 *)(bits)) = (Uint8)color; - break; - case 2: - *((Uint16 *)(bits)) = (Uint16)color; - break; - case 3: { /* Format/endian independent */ - Uint8 r,g,b; - r = (color >> surface->format->Rshift) & 0xFF; - g = (color >> surface->format->Gshift) & 0xFF; - b = (color >> surface->format->Bshift) & 0xFF; - *((bits)+surface->format->Rshift/8) = r; - *((bits)+surface->format->Gshift/8) = g; - *((bits)+surface->format->Bshift/8) = b; - } - break; - case 4: - *((Uint32 *)(bits)) = (Uint32)color; - break; - } -} - -static inline void drawPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) -{ - if(x > surface->clip_rect.x + surface->clip_rect.w || x < surface->clip_rect.x || y > surface->clip_rect.y + surface->clip_rect.h || y < surface->clip_rect.y) - return; - - switch (surface->format->BytesPerPixel) - { - case 1: { /* Assuming 8-bpp */ - - Uint8 *pixel = (Uint8 *)surface->pixels + y*surface->pitch + x; - - Uint8 dR = surface->format->palette->colors[*pixel].r; - Uint8 dG = surface->format->palette->colors[*pixel].g; - Uint8 dB = surface->format->palette->colors[*pixel].b; - Uint8 sR = surface->format->palette->colors[color].r; - Uint8 sG = surface->format->palette->colors[color].g; - Uint8 sB = surface->format->palette->colors[color].b; - - dR = dR + ((sR-dR)*alpha >> 8); - dG = dG + ((sG-dG)*alpha >> 8); - dB = dB + ((sB-dB)*alpha >> 8); - - *pixel = SDL_MapRGB(surface->format, dR, dG, dB); - - } - break; - - case 2: { /* Probably 15-bpp or 16-bpp */ - - Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask; - Uint16 *pixel = (Uint16 *)surface->pixels + y*surface->pitch/2 + x; - Uint32 dc = *pixel; - Uint32 R,G,B,A=0; - - R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask; - G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask; - B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask; - if( Amask ) - A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask; - - *pixel= R | G | B | A; - - } - break; - - case 3: { /* Slow 24-bpp mode, usually not used */ - Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; - Uint8 rshift8=surface->format->Rshift/8; - Uint8 gshift8=surface->format->Gshift/8; - Uint8 bshift8=surface->format->Bshift/8; - Uint8 ashift8=surface->format->Ashift/8; - - - - Uint8 dR, dG, dB, dA; - Uint8 sR, sG, sB, sA; - - pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; - - dR = *((pix)+rshift8); - dG = *((pix)+gshift8); - dB = *((pix)+bshift8); - dA = *((pix)+ashift8); - - sR = (color>>surface->format->Rshift)&0xff; - sG = (color>>surface->format->Gshift)&0xff; - sB = (color>>surface->format->Bshift)&0xff; - sA = (color>>surface->format->Ashift)&0xff; - - dR = dR + ((sR-dR)*alpha >> 8); - dG = dG + ((sG-dG)*alpha >> 8); - dB = dB + ((sB-dB)*alpha >> 8); - dA = dA + ((sA-dA)*alpha >> 8); - - *((pix)+rshift8) = dR; - *((pix)+gshift8) = dG; - *((pix)+bshift8) = dB; - *((pix)+ashift8) = dA; - - } - break; - - case 4: { /* Probably 32-bpp */ - Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask; - Uint32* pixel = (Uint32*)surface->pixels + y*surface->pitch/4 + x; - Uint32 source = *pixel; - Uint32 R,G,B,A; - R = color & Rmask; - G = color & Gmask; - B = color & Bmask; - A = 0; // keep this as 0 to avoid corruption of non-alpha surfaces - - // Blend and keep dest alpha - if( alpha != SDL_ALPHA_OPAQUE ){ - R = ((source & Rmask) + (( R - (source & Rmask) ) * alpha >> 8)) & Rmask; - G = ((source & Gmask) + (( G - (source & Gmask) ) * alpha >> 8)) & Gmask; - B = ((source & Bmask) + (( B - (source & Bmask) ) * alpha >> 8)) & Bmask; - } - if(Amask) - A = (source & Amask); - - *pixel = R | G | B | A; - } - break; - } -} - -static inline NFont::Rectf rectUnion(const NFont::Rectf& A, const NFont::Rectf& B) -{ - float x,x2,y,y2; - x = MIN(A.x, B.x); - y = MIN(A.y, B.y); - x2 = MAX(A.x+A.w, B.x+B.w); - y2 = MAX(A.y+A.h, B.y+B.h); - NFont::Rectf result(x, y, MAX(0, x2 - x), MAX(0, y2 - y)); - return result; -} - -// Adapted from SDL_IntersectRect -static inline NFont::Rectf rectIntersect(const NFont::Rectf& A, const NFont::Rectf& B) -{ - NFont::Rectf result; - float Amin, Amax, Bmin, Bmax; - - // Horizontal intersection - Amin = A.x; - Amax = Amin + A.w; - Bmin = B.x; - Bmax = Bmin + B.w; - if(Bmin > Amin) - Amin = Bmin; - result.x = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.w = Amax - Amin > 0 ? Amax - Amin : 0; - - // Vertical intersection - Amin = A.y; - Amax = Amin + A.h; - Bmin = B.y; - Bmax = Bmin + B.h; - if(Bmin > Amin) - Amin = Bmin; - result.y = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.h = Amax - Amin > 0 ? Amax - Amin : 0; - - return result; -} - -static inline SDL_Surface* copySurface(SDL_Surface *Surface) -{ - return SDL_ConvertSurface(Surface, Surface->format, Surface->flags); -} - - - - - - - - - -NFont::Color::Color() - : r(0), g(0), b(0), a(255) -{} -NFont::Color::Color(Uint8 r, Uint8 g, Uint8 b) - : r(r), g(g), b(b), a(255) -{} -NFont::Color::Color(Uint8 r, Uint8 g, Uint8 b, Uint8 a) - : r(r), g(g), b(b), a(a) -{} -NFont::Color::Color(const SDL_Color& color) - : r(color.r), g(color.g), b(color.b), a(color.a) -{} - -NFont::Color& NFont::Color::rgb(Uint8 R, Uint8 G, Uint8 B) -{ - r = R; - g = G; - b = B; - - return *this; -} - -NFont::Color& NFont::Color::rgba(Uint8 R, Uint8 G, Uint8 B, Uint8 A) -{ - r = R; - g = G; - b = B; - a = A; - - return *this; -} - -NFont::Color& NFont::Color::color(const SDL_Color& color) -{ - r = color.r; - g = color.g; - b = color.b; - a = color.a; - - return *this; -} - -SDL_Color NFont::Color::to_SDL_Color() const -{ - SDL_Color c = {r, g, b, a}; - return c; -} - - - - -NFont::Rectf::Rectf() - : x(0), y(0), w(0), h(0) -{} - -NFont::Rectf::Rectf(float x, float y) - : x(x), y(y), w(0), h(0) -{} - -NFont::Rectf::Rectf(float x, float y, float w, float h) - : x(x), y(y), w(w), h(h) -{} - -NFont::Rectf::Rectf(const SDL_Rect& rect) - : x(rect.x), y(rect.y), w(rect.w), h(rect.h) -{} - -#ifdef NFONT_USE_SDL_GPU -NFont::Rectf::Rectf(const GPU_Rect& rect) - : x(rect.x), y(rect.y), w(rect.w), h(rect.h) -{} -#endif - -SDL_Rect NFont::Rectf::to_SDL_Rect() const -{ - SDL_Rect r = {int(x), int(y), int(w), int(h)}; - return r; -} - -#ifdef NFONT_USE_SDL_GPU -GPU_Rect NFont::Rectf::to_GPU_Rect() const -{ - return GPU_MakeRect(x, y, w, h); -} -#endif - - - - - - - -char* NFont::buffer = NULL; // Shared buffer for efficient drawing - - -// Constructors -NFont::NFont() -{ - init(); -} - - -#ifdef NFONT_USE_SDL_GPU -NFont::NFont(TTF_Font* ttf) -{ - init(); - load(ttf, FC_GetDefaultColor(font)); -} -NFont::NFont(TTF_Font* ttf, const NFont::Color& color) -{ - init(); - load(ttf, color); -} -NFont::NFont(const char* filename_ttf, Uint32 pointSize) -{ - init(); - load(filename_ttf, pointSize); -} -NFont::NFont(const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style) -{ - init(); - load(filename_ttf, pointSize, color, style); -} -NFont::NFont(SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style) -{ - init(); - load(file_rwops_ttf, own_rwops, pointSize, color, style); -} - -#else - -NFont::NFont(NFont_Target* renderer, TTF_Font* ttf) -{ - init(); - load(renderer, ttf, FC_GetDefaultColor(font)); -} -NFont::NFont(NFont_Target* renderer, TTF_Font* ttf, const NFont::Color& color) -{ - init(); - load(renderer, ttf, color); -} -NFont::NFont(NFont_Target* renderer, const char* filename_ttf, Uint32 pointSize) -{ - init(); - load(renderer, filename_ttf, pointSize); -} -NFont::NFont(NFont_Target* renderer, const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style) -{ - init(); - load(renderer, filename_ttf, pointSize, color, style); -} -NFont::NFont(NFont_Target* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style) -{ - init(); - load(renderer, file_rwops_ttf, own_rwops, pointSize, color, style); -} -#endif - - -NFont::~NFont() -{ - FC_FreeFont(font); -} - -void NFont::init() -{ - font = FC_CreateFont(); - - if(buffer == NULL) - buffer = new char[NFONT_BUFFER_SIZE]; -} - - - - - - -void NFont::setLoadingString(const char* str) -{ - FC_SetLoadingString(font, str); -} - -#ifdef NFONT_USE_SDL_GPU -bool NFont::load(TTF_Font* ttf) -#else -bool NFont::load(NFont_Target* renderer, TTF_Font* ttf) -#endif -{ - #ifdef NFONT_USE_SDL_GPU - return load(ttf, FC_GetDefaultColor(font)); - #else - return load(renderer, ttf, Color(0,0,0,255)); - #endif -} - -#ifdef NFONT_USE_SDL_GPU -bool NFont::load(TTF_Font* ttf, const NFont::Color& color) -#else -bool NFont::load(NFont_Target* renderer, TTF_Font* ttf, const NFont::Color& color) -#endif -{ - if(ttf == NULL) - return false; - - #ifndef NFONT_USE_SDL_GPU - if(renderer == NULL) - return false; - #endif - - FC_ClearFont(font); - #ifdef NFONT_USE_SDL_GPU - return FC_LoadFontFromTTF(font, ttf, color.to_SDL_Color()); - #else - return FC_LoadFontFromTTF(font, renderer, ttf, color.to_SDL_Color()); - #endif -} - -#ifdef NFONT_USE_SDL_GPU -bool NFont::load(const char* filename_ttf, Uint32 pointSize) -#else -bool NFont::load(NFont_Target* renderer, const char* filename_ttf, Uint32 pointSize) -#endif -{ - #ifdef NFONT_USE_SDL_GPU - return load(filename_ttf, pointSize, Color(0,0,0,255)); - #else - return load(renderer, filename_ttf, pointSize, Color(0,0,0,255)); - #endif -} - -#ifdef NFONT_USE_SDL_GPU -bool NFont::load(const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style) -#else -bool NFont::load(NFont_Target* renderer, const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style) -#endif -{ - FC_ClearFont(font); - #ifdef NFONT_USE_SDL_GPU - return FC_LoadFont(font, filename_ttf, pointSize, color.to_SDL_Color(), style); - #else - return FC_LoadFont(font, renderer, filename_ttf, pointSize, color.to_SDL_Color(), style); - #endif -} - -#ifdef NFONT_USE_SDL_GPU -bool NFont::load(SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style) -#else -bool NFont::load(NFont_Target* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style) -#endif -{ - FC_ClearFont(font); - #ifdef NFONT_USE_SDL_GPU - return FC_LoadFont_RW(font, file_rwops_ttf, own_rwops, pointSize, color.to_SDL_Color(), style); - #else - return FC_LoadFont_RW(font, renderer, file_rwops_ttf, own_rwops, pointSize, color.to_SDL_Color(), style); - #endif -} - - - -void NFont::free() -{ - FC_ClearFont(font); -} - - - -NFont::Rectf NFont::draw(NFont_Target* dest, float x, float y, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_Draw(font, dest, x, y, "%s", buffer); -} - -/*static int getIndexPastWidth(const char* text, int width, const int* charWidth) -{ - int charnum; - int len = strlen(text); - - for (int index = 0; index < len; index++) - { - char c = text[index]; - charnum = (unsigned char)(c) - 33; - - // spaces and nonprintable characters - if (c == ' ' || charnum > 222) - { - width -= charWidth[0]; - } - else - width -= charWidth[charnum]; - - if(width <= 0) - return index; - } - return 0; -}*/ - - - -/*static list explode(const string& str, char delimiter) -{ - list result; - - size_t oldPos = 0; - size_t pos = str.find_first_of(delimiter); - while(pos != string::npos) - { - result.push_back(str.substr(oldPos, pos - oldPos)); - oldPos = pos+1; - pos = str.find_first_of(delimiter, oldPos); - } - - result.push_back(str.substr(oldPos, string::npos)); - - return result; -}*/ - -NFont::Rectf NFont::drawBox(NFont_Target* dest, const Rectf& box, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(box.x, box.y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawBox(font, dest, box.to_GPU_Rect(), "%s", buffer); - #else - return FC_DrawBox(font, dest, box.to_SDL_Rect(), "%s", buffer); - #endif -} - -static FC_AlignEnum translate_enum_NFont_to_FC(NFont::AlignEnum align) -{ - switch(align) - { - case NFont::LEFT: - return FC_ALIGN_LEFT; - case NFont::CENTER: - return FC_ALIGN_CENTER; - case NFont::RIGHT: - return FC_ALIGN_RIGHT; - default: - return FC_ALIGN_LEFT; - } -} - -NFont::Rectf NFont::drawBox(NFont_Target* dest, const Rectf& box, AlignEnum align, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(box.x, box.y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawBoxAlign(font, dest, box.to_GPU_Rect(), translate_enum_NFont_to_FC(align), "%s", buffer); - #else - return FC_DrawBoxAlign(font, dest, box.to_SDL_Rect(), translate_enum_NFont_to_FC(align), "%s", buffer); - #endif -} - -NFont::Rectf NFont::drawBox(NFont_Target* dest, const Rectf& box, const Scale& scale, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(box.x, box.y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawBoxScale(font, dest, box.to_GPU_Rect(), FC_MakeScale(scale.x, scale.y), "%s", buffer); - #else - return FC_DrawBoxScale(font, dest, box.to_SDL_Rect(), FC_MakeScale(scale.x, scale.y), "%s", buffer); - #endif -} - -NFont::Rectf NFont::drawBox(NFont_Target* dest, const Rectf& box, const Color& color, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(box.x, box.y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawBoxColor(font, dest, box.to_GPU_Rect(), color.to_SDL_Color(), "%s", buffer); - #else - return FC_DrawBoxColor(font, dest, box.to_SDL_Rect(), color.to_SDL_Color(), "%s", buffer); - #endif -} - -NFont::Rectf NFont::drawBox(NFont_Target* dest, const Rectf& box, const Effect& effect, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(box.x, box.y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawBoxEffect(font, dest, box.to_GPU_Rect(), FC_MakeEffect(translate_enum_NFont_to_FC(effect.alignment), FC_MakeScale(effect.scale.x, effect.scale.y), effect.color.to_SDL_Color()), "%s", buffer); - #else - return FC_DrawBoxEffect(font, dest, box.to_SDL_Rect(), FC_MakeEffect(translate_enum_NFont_to_FC(effect.alignment), FC_MakeScale(effect.scale.x, effect.scale.y), effect.color.to_SDL_Color()), "%s", buffer); - #endif -} - -NFont::Rectf NFont::drawColumn(NFont_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawColumn(font, dest, x, y, width, "%s", buffer); -} - -NFont::Rectf NFont::drawColumn(NFont_Target* dest, float x, float y, Uint16 width, AlignEnum align, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawColumnAlign(font, dest, x, y, width, translate_enum_NFont_to_FC(align), "%s", buffer); -} - -NFont::Rectf NFont::drawColumn(NFont_Target* dest, float x, float y, Uint16 width, const Scale& scale, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawColumnScale(font, dest, x, y, width, FC_MakeScale(scale.x, scale.y), "%s", buffer); -} - -NFont::Rectf NFont::drawColumn(NFont_Target* dest, float x, float y, Uint16 width, const Color& color, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawColumnColor(font, dest, x, y, width, color.to_SDL_Color(), "%s", buffer); -} - -NFont::Rectf NFont::drawColumn(NFont_Target* dest, float x, float y, Uint16 width, const Effect& effect, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - #ifdef NFONT_USE_SDL_GPU - return FC_DrawColumnEffect(font, dest, x, y, width, FC_MakeEffect(translate_enum_NFont_to_FC(effect.alignment), FC_MakeScale(effect.scale.x, effect.scale.y), effect.color.to_SDL_Color()), "%s", buffer); - #else - return FC_DrawColumnEffect(font, dest, x, y, width, FC_MakeEffect(translate_enum_NFont_to_FC(effect.alignment), FC_MakeScale(effect.scale.x, effect.scale.y), effect.color.to_SDL_Color()), "%s", buffer); - #endif -} - - - -NFont::Rectf NFont::draw(NFont_Target* dest, float x, float y, const Scale& scale, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawScale(font, dest, x, y, FC_MakeScale(scale.x, scale.y), "%s", buffer); -} - -NFont::Rectf NFont::draw(NFont_Target* dest, float x, float y, AlignEnum align, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawAlign(font, dest, x, y, translate_enum_NFont_to_FC(align), "%s", buffer); -} - -NFont::Rectf NFont::draw(NFont_Target* dest, float x, float y, const Color& color, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawColor(font, dest, x, y, color.to_SDL_Color(), "%s", buffer); -} - - -NFont::Rectf NFont::draw(NFont_Target* dest, float x, float y, const Effect& effect, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_DrawEffect(font, dest, x, y, FC_MakeEffect(translate_enum_NFont_to_FC(effect.alignment), FC_MakeScale(effect.scale.x, effect.scale.y), effect.color.to_SDL_Color()), "%s", buffer); -} - - - - -// Getters - - -NFont::FilterEnum NFont::getFilterMode() const -{ - FC_FilterEnum f = FC_GetFilterMode(font); - if(f == FC_FILTER_LINEAR) - return NFont::LINEAR; - return NFont::NEAREST; -} - -Uint16 NFont::getHeight() const -{ - return FC_GetLineHeight(font); -} - -Uint16 NFont::getHeight(const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return 0; - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetHeight(font, "%s", buffer); -} - -Uint16 NFont::getWidth(const char* formatted_text, ...) -{ - if (formatted_text == NULL) - return 0; - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetWidth(font, "%s", buffer); -} - - -NFont::Rectf NFont::getCharacterOffset(Uint16 position_index, int column_width, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return Rectf(0,0,0,0); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetCharacterOffset(font, position_index, column_width, "%s", buffer); -} - -// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index) -Uint16 NFont::getPositionFromOffset(float x, float y, int column_width, NFont::AlignEnum align, const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return 0; - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetPositionFromOffset(font, x, y, column_width, translate_enum_NFont_to_FC(align), "%s", buffer); -} - - -Uint16 NFont::getColumnHeight(Uint16 width, const char* formatted_text, ...) -{ - if(formatted_text == NULL || width == 0) - return 0; - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetColumnHeight(font, width, "%s", buffer); -} - -int NFont::getAscent(const char character) -{ - return FC_GetAscent(font, "%c", character); -} - -int NFont::getAscent() const -{ - return FC_GetAscent(font, NULL); -} - -int NFont::getAscent(const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return FC_GetAscent(font, NULL); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetAscent(font, "%s", buffer); -} - -int NFont::getDescent(const char character) -{ - return FC_GetDescent(font, "%c", character); -} - -int NFont::getDescent() const -{ - return FC_GetDescent(font, NULL); -} - -int NFont::getDescent(const char* formatted_text, ...) -{ - if(formatted_text == NULL) - return FC_GetDescent(font, NULL); - - va_list lst; - va_start(lst, formatted_text); - vsnprintf(buffer, NFONT_BUFFER_SIZE, formatted_text, lst); - va_end(lst); - - return FC_GetDescent(font, "%s", buffer); -} - -int NFont::getSpacing() const -{ - return FC_GetSpacing(font); -} - -int NFont::getLineSpacing() const -{ - return FC_GetLineSpacing(font); -} - -Uint16 NFont::getBaseline() const -{ - return FC_GetBaseline(font); -} - -Uint16 NFont::getMaxWidth() const -{ - return FC_GetMaxWidth(font); -} - -NFont::Color NFont::getDefaultColor() const -{ - return FC_GetDefaultColor(font); -} - - -int NFont::getNumCacheLevels() const -{ - return FC_GetNumCacheLevels(font); -} - -NFont_Image* NFont::getCacheLevel(int level) const -{ - return FC_GetGlyphCacheLevel(font, level); -} - - - - - -// Setters - -void NFont::setFilterMode(NFont::FilterEnum filter) -{ - if(filter == NFont::LINEAR) - FC_SetFilterMode(font, FC_FILTER_LINEAR); - else - FC_SetFilterMode(font, FC_FILTER_NEAREST); -} - -void NFont::setSpacing(int LetterSpacing) -{ - FC_SetSpacing(font, LetterSpacing); -} - -void NFont::setLineSpacing(int LineSpacing) -{ - FC_SetLineSpacing(font, LineSpacing); -} - -void NFont::setBaseline() -{ - -} - -void NFont::setDefaultColor(const Color& color) -{ - FC_SetDefaultColor(font, color.to_SDL_Color()); -} - -void NFont::enableTTFOwnership() -{ - -} - - - - diff --git a/source/code/Libs/NFont.h b/source/code/Libs/NFont.h deleted file mode 100644 index 27a3f3f..0000000 --- a/source/code/Libs/NFont.h +++ /dev/null @@ -1,320 +0,0 @@ -/* -NFont v5.0.0: A font class for SDL and SDL_Renderer -by Jonathan Dearborn -Dedicated to the memory of Florian Hufsky - -License: - The short: - Use it however you'd like, but keep the copyright and license notice - whenever these files or parts of them are distributed in uncompiled form. - - The long: -Copyright (c) 2016 Jonathan Dearborn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef _NFONT_H__ -#define _NFONT_H__ - -#include "SDL.h" - -#if defined(FC_USE_SDL_GPU) && !defined(NFONT_USE_SDL_GPU) -#define NFONT_USE_SDL_GPU -#endif - -#ifdef NFONT_USE_SDL_GPU - #include "SDL_gpu.h" -#endif - -#ifndef NFONT_FORMAT - -#if ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) -#define NFONT_FORMAT(X) __attribute__ ((format (printf, X, X+1))) -#else -#define NFONT_FORMAT(X) -#endif - -#endif - -#include "stdarg.h" - -// Let's pretend this exists... -#ifndef TTF_STYLE_OUTLINE - #define TTF_STYLE_OUTLINE 16 -#endif - -struct FC_Font; - -typedef struct _TTF_Font TTF_Font; - -// Differences between SDL_Renderer and SDL_gpu -#ifdef NFONT_USE_SDL_GPU -#define NFont_Image GPU_Image -#else -#define NFont_Image SDL_Texture -#endif - -#if defined(NFONT_DLL) || defined(NFONT_DLL_EXPORT) - #ifdef NFONT_DLL_EXPORT - #define NFONT_EXPORT __declspec(dllexport) - #else - #define NFONT_EXPORT __declspec(dllimport) - #endif -#else - #define NFONT_EXPORT -#endif - -class NFONT_EXPORT NFont -{ - public: - - class NFONT_EXPORT Color - { - public: - - Uint8 r, g, b, a; - - Color(); - Color(Uint8 r, Uint8 g, Uint8 b); - Color(Uint8 r, Uint8 g, Uint8 b, Uint8 a); - Color(const SDL_Color& color); - - Color& rgb(Uint8 R, Uint8 G, Uint8 B); - Color& rgba(Uint8 R, Uint8 G, Uint8 B, Uint8 A); - Color& color(const SDL_Color& color); - - SDL_Color to_SDL_Color() const; - }; - - class NFONT_EXPORT Rectf - { - public: - float x, y; - float w, h; - - Rectf(); - Rectf(float x, float y); - Rectf(float x, float y, float w, float h); - Rectf(const SDL_Rect& rect); - - SDL_Rect to_SDL_Rect() const; - - #ifdef NFONT_USE_SDL_GPU - Rectf(const GPU_Rect& rect); - GPU_Rect to_GPU_Rect() const; - #endif - }; - - - enum AlignEnum {LEFT, CENTER, RIGHT}; - enum FilterEnum {NEAREST, LINEAR}; - - class NFONT_EXPORT Scale - { - public: - - float x; - float y; - - enum ScaleTypeEnum {NEAREST}; - ScaleTypeEnum type; - - Scale() - : x(1.0f), y(1.0f), type(NEAREST) - {} - Scale(float xy) - : x(xy), y(xy), type(NEAREST) - {} - Scale(float xy, ScaleTypeEnum type) - : x(xy), y(xy), type(type) - {} - Scale(float x, float y) - : x(x), y(y), type(NEAREST) - {} - Scale(float x, float y, ScaleTypeEnum type) - : x(x), y(y), type(type) - {} - }; - - class NFONT_EXPORT Effect - { - public: - AlignEnum alignment; - Scale scale; - bool use_color; - Color color; - - Effect() - : alignment(LEFT), use_color(false), color(255, 255, 255, 255) - {} - - Effect(const Scale& scale) - : alignment(LEFT), scale(scale), use_color(false), color(255, 255, 255, 255) - {} - Effect(AlignEnum alignment) - : alignment(alignment), use_color(false), color(255, 255, 255, 255) - {} - Effect(const Color& color) - : alignment(LEFT), use_color(true), color(color) - {} - - Effect(AlignEnum alignment, const Scale& scale) - : alignment(alignment), scale(scale), use_color(false), color(255, 255, 255, 255) - {} - Effect(AlignEnum alignment, const Color& color) - : alignment(alignment), use_color(true), color(color) - {} - Effect(const Scale& scale, const Color& color) - : alignment(LEFT), scale(scale), use_color(true), color(color) - {} - Effect(AlignEnum alignment, const Scale& scale, const Color& color) - : alignment(alignment), scale(scale), use_color(true), color(color) - {} - }; - - - // Constructors - NFont(); - NFont(const NFont& font); - #ifdef NFONT_USE_SDL_GPU - NFont(SDL_Surface* src); - NFont(TTF_Font* ttf); - NFont(TTF_Font* ttf, const NFont::Color& color); - NFont(const char* filename_ttf, Uint32 pointSize); - NFont(const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style = 0); - NFont(SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style = 0); - #else - NFont(SDL_Renderer* renderer, SDL_Surface* src); - NFont(SDL_Renderer* renderer, TTF_Font* ttf); - NFont(SDL_Renderer* renderer, TTF_Font* ttf, const NFont::Color& color); - NFont(SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize); - NFont(SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style = 0); - NFont(SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style = 0); - #endif - - ~NFont(); - - NFont& operator=(const NFont& font); - - // Loading - void setLoadingString(const char* str); - - #ifdef NFONT_USE_SDL_GPU - bool load(SDL_Surface* FontSurface); - bool load(TTF_Font* ttf); - bool load(TTF_Font* ttf, const NFont::Color& color); - bool load(const char* filename_ttf, Uint32 pointSize); - bool load(const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style = 0); - bool load(SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style = 0); - #else - bool load(SDL_Renderer* renderer, SDL_Surface* FontSurface); - bool load(SDL_Renderer* renderer, TTF_Font* ttf); - bool load(SDL_Renderer* renderer, TTF_Font* ttf, const NFont::Color& color); - bool load(SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize); - bool load(SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize, const NFont::Color& color, int style = 0); - bool load(SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, const NFont::Color& color, int style = 0); - #endif - - void free(); - - // Drawing - #ifdef NFONT_USE_SDL_GPU - Rectf draw(GPU_Target* dest, float x, float y, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf draw(GPU_Target* dest, float x, float y, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(GPU_Target* dest, float x, float y, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(GPU_Target* dest, float x, float y, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(GPU_Target* dest, float x, float y, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(6); - - Rectf drawBox(GPU_Target* dest, const Rectf& box, const char* formatted_text, ...) NFONT_FORMAT(4); - Rectf drawBox(GPU_Target* dest, const Rectf& box, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(GPU_Target* dest, const Rectf& box, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(GPU_Target* dest, const Rectf& box, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(GPU_Target* dest, const Rectf& box, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(5); - - Rectf drawColumn(GPU_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf drawColumn(GPU_Target* dest, float x, float y, Uint16 width, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(GPU_Target* dest, float x, float y, Uint16 width, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(GPU_Target* dest, float x, float y, Uint16 width, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(GPU_Target* dest, float x, float y, Uint16 width, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(7); - #else - Rectf draw(SDL_Renderer* dest, float x, float y, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf draw(SDL_Renderer* dest, float x, float y, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(SDL_Renderer* dest, float x, float y, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(SDL_Renderer* dest, float x, float y, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf draw(SDL_Renderer* dest, float x, float y, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(6); - - Rectf drawBox(SDL_Renderer* dest, const Rectf& box, const char* formatted_text, ...) NFONT_FORMAT(4); - Rectf drawBox(SDL_Renderer* dest, const Rectf& box, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(SDL_Renderer* dest, const Rectf& box, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(SDL_Renderer* dest, const Rectf& box, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(5); - Rectf drawBox(SDL_Renderer* dest, const Rectf& box, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(5); - - Rectf drawColumn(SDL_Renderer* dest, float x, float y, Uint16 width, const char* formatted_text, ...) NFONT_FORMAT(6); - Rectf drawColumn(SDL_Renderer* dest, float x, float y, Uint16 width, AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(SDL_Renderer* dest, float x, float y, Uint16 width, const Scale& scale, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(SDL_Renderer* dest, float x, float y, Uint16 width, const Color& color, const char* formatted_text, ...) NFONT_FORMAT(7); - Rectf drawColumn(SDL_Renderer* dest, float x, float y, Uint16 width, const Effect& effect, const char* formatted_text, ...) NFONT_FORMAT(7); - #endif - - // Getters - FilterEnum getFilterMode() const; - Uint16 getHeight() const; - Uint16 getHeight(const char* formatted_text, ...) const NFONT_FORMAT(2); - Uint16 getWidth(const char* formatted_text, ...) NFONT_FORMAT(2); - Rectf getCharacterOffset(Uint16 position_index, int column_width, const char* formatted_text, ...) NFONT_FORMAT(4); - Uint16 getPositionFromOffset(float x, float y, int column_width, NFont::AlignEnum align, const char* formatted_text, ...) NFONT_FORMAT(6); - Uint16 getColumnHeight(Uint16 width, const char* formatted_text, ...) NFONT_FORMAT(3); - int getSpacing() const; - int getLineSpacing() const; - Uint16 getBaseline() const; - int getAscent() const; - int getAscent(const char character); - int getAscent(const char* formatted_text, ...) NFONT_FORMAT(2); - int getDescent() const; - int getDescent(const char character); - int getDescent(const char* formatted_text, ...) NFONT_FORMAT(2); - Uint16 getMaxWidth() const; - Color getDefaultColor() const; - - int getNumCacheLevels() const; - NFont_Image* getCacheLevel(int level) const; - - // Setters - void setFilterMode(FilterEnum filter); - void setSpacing(int LetterSpacing); - void setLineSpacing(int LineSpacing); - void setBaseline(); - void setBaseline(Uint16 Baseline); - void setDefaultColor(const Color& color); - - void enableTTFOwnership(); - - private: - - static char* buffer; - FC_Font* font; - - void init(); // Common constructor - -}; - - - -#endif // _NFONT_H__ diff --git a/source/code/Libs/SDL_FontCache.c b/source/code/Libs/SDL_FontCache.c deleted file mode 100644 index 281b375..0000000 --- a/source/code/Libs/SDL_FontCache.c +++ /dev/null @@ -1,2639 +0,0 @@ -/* -SDL_FontCache: A font cache for SDL and SDL_ttf -by Jonathan Dearborn - -See SDL_FontCache.h for license info. -*/ - -#include "SDL_FontCache.h" - -#include -#include -#include - -// Visual C does not support static inline -#ifndef static_inline - #ifdef _MSC_VER - #define static_inline static - #else - #define static_inline static inline - #endif -#endif - -#if SDL_VERSION_ATLEAST(2,0,0) - #define FC_GET_ALPHA(sdl_color) ((sdl_color).a) -#else - #define FC_GET_ALPHA(sdl_color) ((sdl_color).unused) -#endif - -// Need SDL_RenderIsClipEnabled() for proper clipping support -#if SDL_VERSION_ATLEAST(2,0,4) - #define ENABLE_SDL_CLIPPING -#endif - -#define FC_MIN(a,b) ((a) < (b)? (a) : (b)) -#define FC_MAX(a,b) ((a) > (b)? (a) : (b)) - - -// vsnprintf replacement from Valentin Milea: -// http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#define snprintf c99_snprintf -#define vsnprintf c99_vsnprintf - -__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) -{ - int count = -1; - - if (size != 0) - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...) -{ - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(outBuf, size, format, ap); - va_end(ap); - - return count; -} - -#endif - - -#define FC_EXTRACT_VARARGS(buffer, start_args) \ -{ \ - va_list lst; \ - va_start(lst, start_args); \ - vsnprintf(buffer, fc_buffer_size, start_args, lst); \ - va_end(lst); \ -} - -// Extra pixels of padding around each glyph to avoid linear filtering artifacts -#define FC_CACHE_PADDING 1 - - - -static Uint8 has_clip(FC_Target* dest) -{ - #ifdef FC_USE_SDL_GPU - return dest->use_clip_rect; - #elif defined(ENABLE_SDL_CLIPPING) - return SDL_RenderIsClipEnabled(dest); - #else - return 0; - #endif -} - -static FC_Rect get_clip(FC_Target* dest) -{ - #ifdef FC_USE_SDL_GPU - return dest->clip_rect; - #elif defined(ENABLE_SDL_CLIPPING) - SDL_Rect r; - SDL_RenderGetClipRect(dest, &r); - return r; - #else - SDL_Rect r = {0, 0, 0, 0}; - return r; - #endif -} - -static void set_clip(FC_Target* dest, FC_Rect* rect) -{ - #ifdef FC_USE_SDL_GPU - if(rect != NULL) - GPU_SetClipRect(dest, *rect); - else - GPU_UnsetClip(dest); - #elif defined(ENABLE_SDL_CLIPPING) - SDL_RenderSetClipRect(dest, rect); - #endif -} - -static void set_color(FC_Image* src, Uint8 r, Uint8 g, Uint8 b, Uint8 a) -{ - #ifdef FC_USE_SDL_GPU - GPU_SetRGBA(src, r, g, b, a); - #else - SDL_SetTextureColorMod(src, r, g, b); - SDL_SetTextureAlphaMod(src, a); - #endif -} - - - -static char* new_concat(const char* a, const char* b) -{ - // Create new buffer - unsigned int size = strlen(a) + strlen(b); - char* new_string = (char*)malloc(size+1); - - // Concatenate strings in the new buffer - strcpy(new_string, a); - strcat(new_string, b); - - return new_string; -} - -static char* replace_concat(char** a, const char* b) -{ - char* new_string = new_concat(*a, b); - free(*a); - *a = new_string; - return *a; -} - - - - - -// Shared buffer for variadic text -static char* fc_buffer = NULL; -static unsigned int fc_buffer_size = 1024; - -static Uint8 fc_has_render_target_support = 0; - -char* FC_GetStringASCII(void) -{ - static char* buffer = NULL; - if(buffer == NULL) - { - int i; - char c; - buffer = (char*)malloc(512); - memset(buffer, 0, 512); - i = 0; - c = 32; - while(1) - { - buffer[i] = c; - if(c == 126) - break; - ++i; - ++c; - } - } - return U8_strdup(buffer); -} - -char* FC_GetStringLatin1(void) -{ - static char* buffer = NULL; - if(buffer == NULL) - { - int i; - unsigned char c; - buffer = (char*)malloc(512); - memset(buffer, 0, 512); - i = 0; - c = 0xA0; - while(1) - { - buffer[i] = 0xC2; - buffer[i+1] = c; - if(c == 0xBF) - break; - i += 2; - ++c; - } - i += 2; - c = 0x80; - while(1) - { - buffer[i] = 0xC3; - buffer[i+1] = c; - if(c == 0xBF) - break; - i += 2; - ++c; - } - } - return U8_strdup(buffer); -} - -char* FC_GetStringASCII_Latin1(void) -{ - static char* buffer = NULL; - if(buffer == NULL) - buffer = new_concat(FC_GetStringASCII(), FC_GetStringLatin1()); - - return U8_strdup(buffer); -} - -FC_Rect FC_MakeRect(float x, float y, float w, float h) -{ - FC_Rect r = {x, y, w, h}; - return r; -} - -FC_Scale FC_MakeScale(float x, float y) -{ - FC_Scale s = {x, y}; - - return s; -} - -SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) -{ - SDL_Color c = {r, g, b, a}; - - return c; -} - -FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color) -{ - FC_Effect e; - - e.alignment = alignment; - e.scale = scale; - e.color = color; - - return e; -} - -FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h) -{ - FC_GlyphData gd; - - gd.rect.x = x; - gd.rect.y = y; - gd.rect.w = w; - gd.rect.h = h; - gd.cache_level = cache_level; - - return gd; -} - -// Enough to hold all of the ascii characters and some. -#define FC_DEFAULT_NUM_BUCKETS 300 - -typedef struct FC_MapNode -{ - Uint32 key; - FC_GlyphData value; - struct FC_MapNode* next; - -} FC_MapNode; - -typedef struct FC_Map -{ - int num_buckets; - FC_MapNode** buckets; -} FC_Map; - - - -static FC_Map* FC_MapCreate(int num_buckets) -{ - int i; - FC_Map* map = (FC_Map*)malloc(sizeof(FC_Map)); - - map->num_buckets = num_buckets; - map->buckets = (FC_MapNode**)malloc(num_buckets * sizeof(FC_MapNode*)); - - for(i = 0; i < num_buckets; ++i) - { - map->buckets[i] = NULL; - } - - return map; -} - -/*static void FC_MapClear(FC_Map* map) -{ - int i; - if(map == NULL) - return; - - // Go through each bucket - for(i = 0; i < map->num_buckets; ++i) - { - // Delete the nodes in order - FC_MapNode* node = map->buckets[i]; - while(node != NULL) - { - FC_MapNode* last = node; - node = node->next; - free(last); - } - // Set the bucket to empty - map->buckets[i] = NULL; - } -}*/ - -static void FC_MapFree(FC_Map* map) -{ - int i; - if(map == NULL) - return; - - // Go through each bucket - for(i = 0; i < map->num_buckets; ++i) - { - // Delete the nodes in order - FC_MapNode* node = map->buckets[i]; - while(node != NULL) - { - FC_MapNode* last = node; - node = node->next; - free(last); - } - } - - free(map->buckets); - free(map); -} - -// Note: Does not handle duplicates in any special way. -static FC_GlyphData* FC_MapInsert(FC_Map* map, Uint32 codepoint, FC_GlyphData glyph) -{ - Uint32 index; - FC_MapNode* node; - if(map == NULL) - return NULL; - - // Get index for bucket - index = codepoint % map->num_buckets; - - // If this bucket is empty, create a node and return its value - if(map->buckets[index] == NULL) - { - node = map->buckets[index] = (FC_MapNode*)malloc(sizeof(FC_MapNode)); - node->key = codepoint; - node->value = glyph; - node->next = NULL; - return &node->value; - } - - for(node = map->buckets[index]; node != NULL; node = node->next) - { - // Find empty node and add a new one on. - if(node->next == NULL) - { - node->next = (FC_MapNode*)malloc(sizeof(FC_MapNode)); - node = node->next; - - node->key = codepoint; - node->value = glyph; - node->next = NULL; - return &node->value; - } - } - - return NULL; -} - -static FC_GlyphData* FC_MapFind(FC_Map* map, Uint32 codepoint) -{ - Uint32 index; - FC_MapNode* node; - if(map == NULL) - return NULL; - - // Get index for bucket - index = codepoint % map->num_buckets; - - // Go through list until we find a match - for(node = map->buckets[index]; node != NULL; node = node->next) - { - if(node->key == codepoint) - return &node->value; - } - - return NULL; -} - - - -struct FC_Font -{ - #ifndef FC_USE_SDL_GPU - SDL_Renderer* renderer; - #endif - - TTF_Font* ttf_source; // TTF_Font source of characters - Uint8 owns_ttf_source; // Can we delete the TTF_Font ourselves? - - FC_FilterEnum filter; - - SDL_Color default_color; - Uint16 height; - - Uint16 maxWidth; - Uint16 baseline; - int ascent; - int descent; - - int lineSpacing; - int letterSpacing; - - // Uses 32-bit (4-byte) Unicode codepoints to refer to each glyph - // Codepoints are little endian (reversed from UTF-8) so that something like 0x00000005 is ASCII 5 and the map can be indexed by ASCII values - FC_Map* glyphs; - - FC_GlyphData last_glyph; // Texture packing cursor - int glyph_cache_size; - int glyph_cache_count; - FC_Image** glyph_cache; - - char* loading_string; - -}; - -// Private -static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight); - - -static FC_Rect FC_RenderLeft(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text); -static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text); -static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text); - - -static_inline SDL_Surface* FC_CreateSurface32(Uint32 width, Uint32 height) -{ - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); - #else - return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); - #endif -} - - -char* U8_alloc(unsigned int size) -{ - char* result; - if(size == 0) - return NULL; - - result = (char*)malloc(size); - result[0] = '\0'; - - return result; -} - -void U8_free(char* string) -{ - free(string); -} - -char* U8_strdup(const char* string) -{ - char* result; - if(string == NULL) - return NULL; - - result = (char*)malloc(strlen(string)+1); - strcpy(result, string); - - return result; -} - -int U8_strlen(const char* string) -{ - int length = 0; - if(string == NULL) - return 0; - - while(*string != '\0') - { - string = U8_next(string); - ++length; - } - - return length; -} - -int U8_charsize(const char* character) -{ - if(character == NULL) - return 0; - - if((unsigned char)*character <= 0x7F) - return 1; - else if((unsigned char)*character < 0xE0) - return 2; - else if((unsigned char)*character < 0xF0) - return 3; - else - return 4; - return 1; -} - -int U8_charcpy(char* buffer, const char* source, int buffer_size) -{ - int charsize; - if(buffer == NULL || source == NULL || buffer_size < 1) - return 0; - - charsize = U8_charsize(source); - if(charsize > buffer_size) - return 0; - - memcpy(buffer, source, charsize); - return charsize; -} - -const char* U8_next(const char* string) -{ - return string + U8_charsize(string); -} - -int U8_strinsert(char* string, int position, const char* source, int max_bytes) -{ - int pos_bytes; - int len; - int add_len; - int ulen; - - if(string == NULL || source == NULL) - return 0; - - len = strlen(string); - add_len = strlen(source); - ulen = U8_strlen(string); - - if(position == -1) - position = ulen; - - if(position < 0 || position > ulen || len + add_len + 1 > max_bytes) - return 0; - - // Move string pointer to the proper position - pos_bytes = 0; - while(*string != '\0' && pos_bytes < position) - { - string = (char*)U8_next(string); - ++pos_bytes; - } - - // Move the rest of the string out of the way - memmove(string + add_len, string, len - pos_bytes + 1); - - // Copy in the new characters - memcpy(string, source, add_len); - - return 1; -} - -void U8_strdel(char* string, int position) -{ - if(string == NULL || position < 0) - return; - - while(*string != '\0') - { - if(position == 0) - { - int chars_to_erase = U8_charsize(string); - int remaining_bytes = strlen(string) + 1; - memmove(string, string + chars_to_erase, remaining_bytes); - break; - } - - string = (char*)U8_next(string); - --position; - } -} - - - - - -static_inline FC_Rect FC_RectUnion(FC_Rect A, FC_Rect B) -{ - float x,x2,y,y2; - x = FC_MIN(A.x, B.x); - y = FC_MIN(A.y, B.y); - x2 = FC_MAX(A.x+A.w, B.x+B.w); - y2 = FC_MAX(A.y+A.h, B.y+B.h); - { - FC_Rect result = {x, y, FC_MAX(0, x2 - x), FC_MAX(0, y2 - y)}; - return result; - } -} - -// Adapted from SDL_IntersectRect -static_inline FC_Rect FC_RectIntersect(FC_Rect A, FC_Rect B) -{ - FC_Rect result; - float Amin, Amax, Bmin, Bmax; - - // Horizontal intersection - Amin = A.x; - Amax = Amin + A.w; - Bmin = B.x; - Bmax = Bmin + B.w; - if(Bmin > Amin) - Amin = Bmin; - result.x = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.w = Amax - Amin > 0 ? Amax - Amin : 0; - - // Vertical intersection - Amin = A.y; - Amax = Amin + A.h; - Bmin = B.y; - Bmax = Bmin + B.h; - if(Bmin > Amin) - Amin = Bmin; - result.y = Amin; - if(Bmax < Amax) - Amax = Bmax; - result.h = Amax - Amin > 0 ? Amax - Amin : 0; - - return result; -} - - - - - - - - - - - - - - -FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) -{ - float w = srcrect->w * xscale; - float h = srcrect->h * yscale; - FC_Rect result; - - // FIXME: Why does the scaled offset look so wrong? - #ifdef FC_USE_SDL_GPU - { - GPU_Rect r = *srcrect; - GPU_BlitScale(src, &r, dest, x + xscale*r.w/2.0f, y + r.h/2.0f, xscale, yscale); - } - #else - { - SDL_RendererFlip flip = SDL_FLIP_NONE; - if(xscale < 0) - { - xscale = -xscale; - flip = (SDL_RendererFlip) ((int)flip | (int)SDL_FLIP_HORIZONTAL); - } - if(yscale < 0) - { - yscale = -yscale; - flip = (SDL_RendererFlip) ((int)flip | (int)SDL_FLIP_VERTICAL); - } - - SDL_Rect r = *srcrect; - SDL_Rect dr = {(int)x, (int)y, (int)(xscale*r.w), (int)(yscale*r.h)}; - SDL_RenderCopyEx(dest, src, &r, &dr, 0, NULL, flip); - } - #endif - - result.x = x; - result.y = y; - result.w = w; - result.h = h; - return result; -} - -static FC_Rect (*fc_render_callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) = &FC_DefaultRenderCallback; - -void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale)) -{ - if(callback == NULL) - fc_render_callback = &FC_DefaultRenderCallback; - else - fc_render_callback = callback; -} - -void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint) -{ - char a, b, c, d; - - if(result == NULL) - return; - - a = (codepoint >> 24) & 0xFF; - b = (codepoint >> 16) & 0xFF; - c = (codepoint >> 8) & 0xFF; - d = codepoint & 0xFF; - - if(a == 0) - { - if(b == 0) - { - if(c == 0) - { - result[0] = d; - result[1] = '\0'; - } - else - { - result[0] = c; - result[1] = d; - result[2] = '\0'; - } - } - else - { - result[0] = b; - result[1] = c; - result[2] = d; - result[3] = '\0'; - } - } - else - { - result[0] = a; - result[1] = b; - result[2] = c; - result[3] = d; - result[4] = '\0'; - } -} - -Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer) -{ - Uint32 result = 0; - const char* str; - if(c == NULL || *c == NULL) - return 0; - - str = *c; - if((unsigned char)*str <= 0x7F) - result = *str; - else if((unsigned char)*str < 0xE0) - { - result |= (unsigned char)(*str) << 8; - result |= (unsigned char)(*(str+1)); - if(advance_pointer) - *c += 1; - } - else if((unsigned char)*str < 0xF0) - { - result |= (unsigned char)(*str) << 16; - result |= (unsigned char)(*(str+1)) << 8; - result |= (unsigned char)(*(str+2)); - if(advance_pointer) - *c += 2; - } - else - { - result |= (unsigned char)(*str) << 24; - result |= (unsigned char)(*(str+1)) << 16; - result |= (unsigned char)(*(str+2)) << 8; - result |= (unsigned char)(*(str+3)); - if(advance_pointer) - *c += 3; - } - return result; -} - - -void FC_SetLoadingString(FC_Font* font, const char* string) -{ - if(font == NULL) - return; - - free(font->loading_string); - font->loading_string = U8_strdup(string); -} - - -unsigned int FC_GetBufferSize(void) -{ - return fc_buffer_size; -} - -void FC_SetBufferSize(unsigned int size) -{ - free(fc_buffer); - if(size > 0) - { - fc_buffer_size = size; - fc_buffer = (char*)malloc(fc_buffer_size); - } - else - fc_buffer = (char*)malloc(fc_buffer_size); -} - - - - - -// Constructors - -static void FC_Init(FC_Font* font) -{ - if(font == NULL) - return; - - #ifndef FC_USE_SDL_GPU - font->renderer = NULL; - #endif - - font->ttf_source = NULL; - font->owns_ttf_source = 0; - - font->filter = FC_FILTER_NEAREST; - - font->default_color.r = 0; - font->default_color.g = 0; - font->default_color.b = 0; - FC_GET_ALPHA(font->default_color) = 255; - - font->height = 0; // ascent+descent - - font->maxWidth = 0; - font->baseline = 0; - font->ascent = 0; - font->descent = 0; - - font->lineSpacing = 0; - font->letterSpacing = 0; - - // Give a little offset for when filtering/mipmaps are used. Depending on mipmap level, this will still not be enough. - font->last_glyph.rect.x = FC_CACHE_PADDING; - font->last_glyph.rect.y = FC_CACHE_PADDING; - font->last_glyph.rect.w = 0; - font->last_glyph.rect.h = 0; - font->last_glyph.cache_level = 0; - - if(font->glyphs != NULL) - FC_MapFree(font->glyphs); - - font->glyphs = FC_MapCreate(FC_DEFAULT_NUM_BUCKETS); - - font->glyph_cache_size = 3; - font->glyph_cache_count = 0; - - - font->glyph_cache = (FC_Image**)malloc(font->glyph_cache_size * sizeof(FC_Image*)); - - if (font->loading_string == NULL) - font->loading_string = FC_GetStringASCII(); - - if(fc_buffer == NULL) - fc_buffer = (char*)malloc(fc_buffer_size); -} - -static Uint8 FC_GrowGlyphCache(FC_Font* font) -{ - if(font == NULL) - return 0; - #ifdef FC_USE_SDL_GPU - GPU_Image* new_level = GPU_CreateImage(font->height * 12, font->height * 12, GPU_FORMAT_RGBA); - #else - SDL_Texture* new_level = SDL_CreateTexture(font->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, font->height * 12, font->height * 12); - #endif - if(new_level == NULL || !FC_SetGlyphCacheLevel(font, font->glyph_cache_count, new_level)) - { - FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n"); - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(new_level); - #else - SDL_DestroyTexture(new_level); - #endif - return 0; - } - return 1; -} - -Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface) -{ - if(font == NULL || data_surface == NULL) - return 0; - #ifdef FC_USE_SDL_GPU - GPU_Image* new_level = GPU_CopyImageFromSurface(data_surface); - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - GPU_SetImageFilter(new_level, GPU_FILTER_LINEAR); - else - GPU_SetImageFilter(new_level, GPU_FILTER_NEAREST); - #else - SDL_Texture* new_level; - if(!fc_has_render_target_support) - new_level = SDL_CreateTextureFromSurface(font->renderer, data_surface); - else - { - // Must upload with render target enabled so we can put more glyphs on later - SDL_Renderer* renderer = font->renderer; - - // Set filter mode for new texture - char old_filter_mode[16]; // Save it so we can change the hint value in the meantime - snprintf(old_filter_mode, 16, "%s", SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY)); - - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); - else - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - - new_level = SDL_CreateTexture(renderer, data_surface->format->format, SDL_TEXTUREACCESS_TARGET, data_surface->w, data_surface->h); - SDL_SetTextureBlendMode(new_level, SDL_BLENDMODE_BLEND); - - // Reset filter mode for the temp texture - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - - { - Uint8 r, g, b, a; - SDL_Texture* temp = SDL_CreateTextureFromSurface(renderer, data_surface); - SDL_SetTextureBlendMode(temp, SDL_BLENDMODE_NONE); - SDL_SetRenderTarget(renderer, new_level); - - SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); - SDL_RenderClear(renderer); - SDL_SetRenderDrawColor(renderer, r, g, b, a); - - SDL_RenderCopy(renderer, temp, NULL, NULL); - SDL_SetRenderTarget(renderer, NULL); - - SDL_DestroyTexture(temp); - } - - // Reset to the old filter value - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, old_filter_mode); - - } - #endif - if(new_level == NULL || !FC_SetGlyphCacheLevel(font, cache_level, new_level)) - { - FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n"); - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(new_level); - #else - SDL_DestroyTexture(new_level); - #endif - return 0; - } - return 1; -} - -static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight) -{ - FC_Map* glyphs = font->glyphs; - FC_GlyphData* last_glyph = &font->last_glyph; - Uint16 height = font->height + FC_CACHE_PADDING; - - if(last_glyph->rect.x + last_glyph->rect.w + width >= maxWidth - FC_CACHE_PADDING) - { - if(last_glyph->rect.y + height + height >= maxHeight - FC_CACHE_PADDING) - { - // Get ready to pack on the next cache level when it is ready - last_glyph->cache_level = font->glyph_cache_count; - last_glyph->rect.x = FC_CACHE_PADDING; - last_glyph->rect.y = FC_CACHE_PADDING; - last_glyph->rect.w = 0; - return NULL; - } - else - { - // Go to next row - last_glyph->rect.x = FC_CACHE_PADDING; - last_glyph->rect.y += height; - last_glyph->rect.w = 0; - } - } - - // Move to next space - last_glyph->rect.x += last_glyph->rect.w + 1 + FC_CACHE_PADDING; - last_glyph->rect.w = width; - - return FC_MapInsert(glyphs, codepoint, FC_MakeGlyphData(last_glyph->cache_level, last_glyph->rect.x, last_glyph->rect.y, last_glyph->rect.w, last_glyph->rect.h)); -} - - -FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level) -{ - if(font == NULL || cache_level < 0 || cache_level > font->glyph_cache_count) - return NULL; - - return font->glyph_cache[cache_level]; -} - -Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture) -{ - if(font == NULL || cache_level < 0) - return 0; - - // Must be sequentially added - if(cache_level > font->glyph_cache_count + 1) - return 0; - - if(cache_level == font->glyph_cache_count) - { - font->glyph_cache_count++; - - // Grow cache? - if(font->glyph_cache_count > font->glyph_cache_size) - { - // Copy old cache to new one - int i; - FC_Image** new_cache; - new_cache = (FC_Image**)malloc(font->glyph_cache_count * sizeof(FC_Image*)); - for(i = 0; i < font->glyph_cache_size; ++i) - new_cache[i] = font->glyph_cache[i]; - - // Save new cache - free(font->glyph_cache); - font->glyph_cache_size = font->glyph_cache_count; - font->glyph_cache = new_cache; - } - } - - font->glyph_cache[cache_level] = cache_texture; - return 1; -} - - -FC_Font* FC_CreateFont(void) -{ - FC_Font* font; - - font = (FC_Font*)malloc(sizeof(FC_Font)); - memset(font, 0, sizeof(FC_Font)); - - FC_Init(font); - - return font; -} - - -// Assume this many will be enough... -#define FC_LOAD_MAX_SURFACES 10 - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color) -#else -Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color) -#endif -{ - if(font == NULL || ttf == NULL) - return 0; - #ifndef FC_USE_SDL_GPU - if(renderer == NULL) - return 0; - #endif - - FC_ClearFont(font); - - - // Might as well check render target support here - #ifdef FC_USE_SDL_GPU - fc_has_render_target_support = GPU_IsFeatureEnabled(GPU_FEATURE_RENDER_TARGETS); - #else - SDL_RendererInfo info; - SDL_GetRendererInfo(renderer, &info); - fc_has_render_target_support = (info.flags & SDL_RENDERER_TARGETTEXTURE); - - font->renderer = renderer; - #endif - - font->ttf_source = ttf; - - //font->line_height = TTF_FontLineSkip(ttf); - font->height = TTF_FontHeight(ttf); - font->ascent = TTF_FontAscent(ttf); - font->descent = -TTF_FontDescent(ttf); - - font->baseline = font->height - font->descent; - - font->default_color = color; - - { - SDL_Color white = {255, 255, 255, 255}; - SDL_Surface* glyph_surf; - char buff[5]; - const char* buff_ptr = buff; - const char* source_string; - Uint8 packed = 0; - - // Copy glyphs from the surface to the font texture and store the position data - // Pack row by row into a square texture - // Try figuring out dimensions that make sense for the font size. - unsigned int w = font->height*12; - unsigned int h = font->height*12; - SDL_Surface* surfaces[FC_LOAD_MAX_SURFACES]; - int num_surfaces = 1; - surfaces[0] = FC_CreateSurface32(w, h); - font->last_glyph.rect.x = FC_CACHE_PADDING; - font->last_glyph.rect.y = FC_CACHE_PADDING; - font->last_glyph.rect.w = 0; - font->last_glyph.rect.h = font->height; - - memset(buff, 0, 5); - source_string = font->loading_string; - for(; *source_string != '\0'; source_string = U8_next(source_string)) - { - if(!U8_charcpy(buff, source_string, 5)) - continue; - glyph_surf = TTF_RenderUTF8_Blended(ttf, buff, white); - if(glyph_surf == NULL) - continue; - - // Try packing. If it fails, create a new surface for the next cache level. - packed = (FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL); - if(!packed) - { - int i = num_surfaces-1; - if(num_surfaces >= FC_LOAD_MAX_SURFACES) - { - // Can't do any more! - FC_Log("SDL_FontCache error: Could not create enough cache surfaces to fit all of the loading string!\n"); - SDL_FreeSurface(glyph_surf); - break; - } - - // Upload the current surface to the glyph cache now so we can keep the cache level packing cursor up to date as we go. - FC_UploadGlyphCache(font, i, surfaces[i]); - SDL_FreeSurface(surfaces[i]); - #ifndef FC_USE_SDL_GPU - SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND); - #endif - // Update the glyph cursor to the new cache level. We need to do this here because the actual cache lags behind our use of the packing above. - font->last_glyph.cache_level = num_surfaces; - - - surfaces[num_surfaces] = FC_CreateSurface32(w, h); - num_surfaces++; - } - - // Try packing for the new surface, then blit onto it. - if(packed || FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL) - { - SDL_SetSurfaceBlendMode(glyph_surf, SDL_BLENDMODE_NONE); - SDL_Rect srcRect = {0, 0, glyph_surf->w, glyph_surf->h}; - SDL_Rect destrect = font->last_glyph.rect; - SDL_BlitSurface(glyph_surf, &srcRect, surfaces[num_surfaces-1], &destrect); - } - - SDL_FreeSurface(glyph_surf); - } - - { - int i = num_surfaces-1; - FC_UploadGlyphCache(font, i, surfaces[i]); - SDL_FreeSurface(surfaces[i]); - #ifndef FC_USE_SDL_GPU - SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND); - #endif - } - } - - return 1; -} - - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style) -#else -Uint8 FC_LoadFont(FC_Font* font, FC_Target* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style) -#endif -{ - SDL_RWops* rwops; - - if(font == NULL) - return 0; - - rwops = SDL_RWFromFile(filename_ttf, "rb"); - - if(rwops == NULL) - { - FC_Log("Unable to open file for reading: %s \n", SDL_GetError()); - return 0; - } - - #ifdef FC_USE_SDL_GPU - return FC_LoadFont_RW(font, rwops, 1, pointSize, color, style); - #else - return FC_LoadFont_RW(font, renderer, rwops, 1, pointSize, color, style); - #endif -} - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style) -#else -Uint8 FC_LoadFont_RW(FC_Font* font, FC_Target* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style) -#endif -{ - Uint8 result; - TTF_Font* ttf; - Uint8 outline; - - if(font == NULL) - return 0; - - if(!TTF_WasInit() && TTF_Init() < 0) - { - FC_Log("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); - if(own_rwops) - SDL_RWclose(file_rwops_ttf); - return 0; - } - - ttf = TTF_OpenFontRW(file_rwops_ttf, own_rwops, pointSize); - - if(ttf == NULL) - { - FC_Log("Unable to load TrueType font: %s \n", TTF_GetError()); - if(own_rwops) - SDL_RWclose(file_rwops_ttf); - return 0; - } - - outline = (style & TTF_STYLE_OUTLINE); - if(outline) - { - style &= ~TTF_STYLE_OUTLINE; - TTF_SetFontOutline(ttf, 1); - } - TTF_SetFontStyle(ttf, style); - - #ifdef FC_USE_SDL_GPU - result = FC_LoadFontFromTTF(font, ttf, color); - #else - result = FC_LoadFontFromTTF(font, renderer, ttf, color); - #endif - - // Can only load new (uncached) glyphs if we can keep the SDL_RWops open. - font->owns_ttf_source = own_rwops; - if(!own_rwops) - { - TTF_CloseFont(font->ttf_source); - font->ttf_source = NULL; - } - - return result; -} - - -void FC_ClearFont(FC_Font* font) -{ - int i; - if(font == NULL) - return; - - // Release resources - if(font->owns_ttf_source) - TTF_CloseFont(font->ttf_source); - - font->owns_ttf_source = 0; - font->ttf_source = NULL; - - // Delete glyph map - FC_MapFree(font->glyphs); - font->glyphs = NULL; - - // Delete glyph cache - for(i = 0; i < font->glyph_cache_count; ++i) - { - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(font->glyph_cache[i]); - #else - SDL_DestroyTexture(font->glyph_cache[i]); - #endif - } - free(font->glyph_cache); - font->glyph_cache = NULL; - - // Reset font - FC_Init(font); -} - - -void FC_FreeFont(FC_Font* font) -{ - int i; - if(font == NULL) - return; - - // Release resources - if(font->owns_ttf_source) - TTF_CloseFont(font->ttf_source); - - // Delete glyph map - FC_MapFree(font->glyphs); - - // Delete glyph cache - for(i = 0; i < font->glyph_cache_count; ++i) - { - #ifdef FC_USE_SDL_GPU - GPU_FreeImage(font->glyph_cache[i]); - #else - SDL_DestroyTexture(font->glyph_cache[i]); - #endif - } - free(font->glyph_cache); - - free(font->loading_string); - - free(font); -} - -int FC_GetNumCacheLevels(FC_Font* font) -{ - return font->glyph_cache_count; -} - -Uint8 FC_AddGlyphToCache(FC_Font* font, SDL_Surface* glyph_surface) -{ - if(font == NULL || glyph_surface == NULL) - return 0; - - SDL_SetSurfaceBlendMode(glyph_surface, SDL_BLENDMODE_NONE); - FC_Image* dest = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level); - if(dest == NULL) - return 0; - - #ifdef FC_USE_SDL_GPU - { - GPU_Target* target = GPU_LoadTarget(dest); - if(target == NULL) - return 0; - GPU_Image* img = GPU_CopyImageFromSurface(glyph_surface); - GPU_SetImageFilter(img, GPU_FILTER_NEAREST); - GPU_SetBlendMode(img, GPU_BLEND_SET); - - SDL_Rect destrect = font->last_glyph.rect; - GPU_Blit(img, NULL, target, destrect.x + destrect.w/2, destrect.y + destrect.h/2); - - GPU_FreeImage(img); - GPU_FreeTarget(target); - } - #else - { - SDL_Renderer* renderer = font->renderer; - Uint8 use_clip; - FC_Rect clip_rect; - SDL_Texture* img; - SDL_Rect destrect; - - use_clip = has_clip(renderer); - if(use_clip) - { - clip_rect = get_clip(renderer); - set_clip(renderer, NULL); - } - - img = SDL_CreateTextureFromSurface(renderer, glyph_surface); - - destrect = font->last_glyph.rect; - SDL_SetRenderTarget(renderer, dest); - SDL_RenderCopy(renderer, img, NULL, &destrect); - SDL_SetRenderTarget(renderer, NULL); - SDL_DestroyTexture(img); - - if(use_clip) - set_clip(renderer, &clip_rect); - } - #endif - - return 1; -} - - -unsigned int FC_GetNumCodepoints(FC_Font* font) -{ - FC_Map* glyphs; - int i; - unsigned int result = 0; - if(font == NULL || font->glyphs == NULL) - return 0; - - glyphs = font->glyphs; - - for(i = 0; i < glyphs->num_buckets; ++i) - { - FC_MapNode* node; - for(node = glyphs->buckets[i]; node != NULL; node = node->next) - { - result++; - } - } - - return result; -} - -void FC_GetCodepoints(FC_Font* font, Uint32* result) -{ - FC_Map* glyphs; - int i; - unsigned int count = 0; - if(font == NULL || font->glyphs == NULL) - return; - - glyphs = font->glyphs; - - for(i = 0; i < glyphs->num_buckets; ++i) - { - FC_MapNode* node; - for(node = glyphs->buckets[i]; node != NULL; node = node->next) - { - result[count] = node->key; - count++; - } - } -} - -Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint) -{ - FC_GlyphData* e = FC_MapFind(font->glyphs, codepoint); - if(e == NULL) - { - char buff[5]; - int w, h; - SDL_Color white = {255, 255, 255, 255}; - SDL_Surface* surf; - FC_Image* cache_image; - - if(font->ttf_source == NULL) - return 0; - - FC_GetUTF8FromCodepoint(buff, codepoint); - - cache_image = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level); - if(cache_image == NULL) - { - FC_Log("SDL_FontCache: Failed to load cache image, so cannot add new glyphs!\n"); - return 0; - } - - #ifdef FC_USE_SDL_GPU - w = cache_image->w; - h = cache_image->h; - #else - SDL_QueryTexture(cache_image, NULL, NULL, &w, &h); - #endif - - surf = TTF_RenderUTF8_Blended(font->ttf_source, buff, white); - if(surf == NULL) - { - return 0; - } - - e = FC_PackGlyphData(font, codepoint, surf->w, w, h); - if(e == NULL) - { - // Grow the cache - FC_GrowGlyphCache(font); - - // Try packing again - e = FC_PackGlyphData(font, codepoint, surf->w, w, h); - if(e == NULL) - { - SDL_FreeSurface(surf); - return 0; - } - } - - // Render onto the cache texture - FC_AddGlyphToCache(font, surf); - - SDL_FreeSurface(surf); - } - - if(result != NULL && e != NULL) - *result = *e; - - return 1; -} - - -FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data) -{ - return FC_MapInsert(font->glyphs, codepoint, glyph_data); -} - - - -// Drawing -static FC_Rect FC_RenderLeft(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) -{ - const char* c = text; - FC_Rect srcRect; - FC_Rect dstRect; - FC_Rect dirtyRect = FC_MakeRect(x, y, 0, 0); - - FC_GlyphData glyph; - Uint32 codepoint; - - float destX = x; - float destY = y; - float destH; - float destLineSpacing; - float destLetterSpacing; - - if(font == NULL) - return dirtyRect; - - destH = font->height * scale.y; - destLineSpacing = font->lineSpacing*scale.y; - destLetterSpacing = font->letterSpacing*scale.x; - - if(c == NULL || font->glyph_cache_count == 0 || dest == NULL) - return dirtyRect; - - int newlineX = x; - - for(; *c != '\0'; c++) - { - if(*c == '\n') - { - destX = newlineX; - destY += destH + destLineSpacing; - continue; - } - - codepoint = FC_GetCodepointFromUTF8(&c, 1); // Increments 'c' to skip the extra UTF-8 bytes - if(!FC_GetGlyphData(font, &glyph, codepoint)) - { - codepoint = ' '; - if(!FC_GetGlyphData(font, &glyph, codepoint)) - continue; // Skip bad characters - } - - if (codepoint == ' ') - { - destX += glyph.rect.w*scale.x + destLetterSpacing; - continue; - } - /*if(destX >= dest->w) - continue; - if(destY >= dest->h) - continue;*/ - - #ifdef FC_USE_SDL_GPU - srcRect.x = glyph.rect.x; - srcRect.y = glyph.rect.y; - srcRect.w = glyph.rect.w; - srcRect.h = glyph.rect.h; - #else - srcRect = glyph.rect; - #endif - dstRect = fc_render_callback(FC_GetGlyphCacheLevel(font, glyph.cache_level), &srcRect, dest, destX, destY, scale.x, scale.y); - if(dirtyRect.w == 0 || dirtyRect.h == 0) - dirtyRect = dstRect; - else - dirtyRect = FC_RectUnion(dirtyRect, dstRect); - - destX += glyph.rect.w*scale.x + destLetterSpacing; - } - - return dirtyRect; -} - -static void set_color_for_all_caches(FC_Font* font, SDL_Color color) -{ - // TODO: How can I predict which glyph caches are to be used? - FC_Image* img; - int i; - int num_levels = FC_GetNumCacheLevels(font); - for(i = 0; i < num_levels; ++i) - { - img = FC_GetGlyphCacheLevel(font, i); - set_color(img, color.r, color.g, color.b, FC_GET_ALPHA(color)); - } -} - -FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); -} - - - -typedef struct FC_StringList -{ - char* value; - struct FC_StringList* next; -} FC_StringList; - -void FC_StringListFree(FC_StringList* node) -{ - // Delete the nodes in order - while(node != NULL) - { - FC_StringList* last = node; - node = node->next; - - free(last->value); - free(last); - } -} - -FC_StringList** FC_StringListPushBack(FC_StringList** node, char* value, Uint8 copy) -{ - if(node == NULL) - { - return node; - } - - // Get to the last node - while(*node != NULL) - { - node = &(*node)->next; - } - - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - - (*node)->value = (copy? U8_strdup(value) : value); - (*node)->next = NULL; - - return node; -} - -static FC_StringList* FC_Explode(const char* text, char delimiter) -{ - FC_StringList* head; - FC_StringList* new_node; - FC_StringList** node; - const char* start; - const char* end; - unsigned int size; - if(text == NULL) - return NULL; - - head = NULL; - node = &head; - - // Doesn't technically support UTF-8, but it's probably fine, right? - size = 0; - start = end = text; - while(1) - { - if(*end == delimiter || *end == '\0') - { - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - new_node = *node; - - new_node->value = (char*)malloc(size + 1); - memcpy(new_node->value, start, size); - new_node->value[size] = '\0'; - - new_node->next = NULL; - - if(*end == '\0') - break; - - node = &((*node)->next); - start = end+1; - size = 0; - } - else - ++size; - - ++end; - } - - return head; -} - -static FC_StringList* FC_ExplodeAndKeep(const char* text, char delimiter) -{ - FC_StringList* head; - FC_StringList* new_node; - FC_StringList** node; - const char* start; - const char* end; - unsigned int size; - if(text == NULL) - return NULL; - - head = NULL; - node = &head; - - // Doesn't technically support UTF-8, but it's probably fine, right? - size = 0; - start = end = text; - while(1) - { - if(*end == delimiter || *end == '\0') - { - *node = (FC_StringList*)malloc(sizeof(FC_StringList)); - new_node = *node; - - new_node->value = (char*)malloc(size + 1); - memcpy(new_node->value, start, size); - new_node->value[size] = '\0'; - - new_node->next = NULL; - - if(*end == '\0') - break; - - node = &((*node)->next); - start = end; - size = 1; - } - else - ++size; - - ++end; - } - - return head; -} - -static void FC_RenderAlign(FC_Font* font, FC_Target* dest, float x, float y, int width, FC_Scale scale, FC_AlignEnum align, const char* text) -{ - switch(align) - { - case FC_ALIGN_LEFT: - FC_RenderLeft(font, dest, x, y, scale, text); - break; - case FC_ALIGN_CENTER: - FC_RenderCenter(font, dest, x + width/2, y, scale, text); - break; - case FC_ALIGN_RIGHT: - FC_RenderRight(font, dest, x + width, y, scale, text); - break; - } -} - -static FC_StringList* FC_GetBufferFitToColumn(FC_Font* font, int width, FC_Scale scale, Uint8 keep_newlines) -{ - FC_StringList* result = NULL; - FC_StringList** current = &result; - - FC_StringList *ls, *iter; - - ls = (keep_newlines? FC_ExplodeAndKeep(fc_buffer, '\n') : FC_Explode(fc_buffer, '\n')); - for(iter = ls; iter != NULL; iter = iter->next) - { - char* line = iter->value; - - // If line is too long, then add words one at a time until we go over. - if(width > 0 && FC_GetWidth(font, "%s", line) > width) - { - FC_StringList *words, *word_iter; - - words = FC_Explode(line, ' '); - // Skip the first word for the iterator, so there will always be at least one word per line - line = new_concat(words->value, " "); - for(word_iter = words->next; word_iter != NULL; word_iter = word_iter->next) - { - char* line_plus_word = new_concat(line, word_iter->value); - char* word_plus_space = new_concat(word_iter->value, " "); - if(FC_GetWidth(font, "%s", line_plus_word) > width) - { - current = FC_StringListPushBack(current, line, 0); - - line = word_plus_space; - } - else - { - replace_concat(&line, word_plus_space); - free(word_plus_space); - } - free(line_plus_word); - } - current = FC_StringListPushBack(current, line, 0); - FC_StringListFree(words); - } - else - { - current = FC_StringListPushBack(current, line, 0); - iter->value = NULL; - } - } - FC_StringListFree(ls); - - return result; -} - -static void FC_DrawColumnFromBuffer(FC_Font* font, FC_Target* dest, FC_Rect box, int* total_height, FC_Scale scale, FC_AlignEnum align) -{ - int y = box.y; - FC_StringList *ls, *iter; - - ls = FC_GetBufferFitToColumn(font, box.w, scale, 0); - for(iter = ls; iter != NULL; iter = iter->next) - { - FC_RenderAlign(font, dest, box.x, y, box.w, scale, align, iter->value); - y += FC_GetLineHeight(font); - } - FC_StringListFree(ls); - - if(total_height != NULL) - *total_height = y - box.y; -} - -FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), align); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, scale, FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...) -{ - Uint8 useClip; - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(box.x, box.y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - useClip = has_clip(dest); - FC_Rect oldclip, newclip; - if(useClip) - { - oldclip = get_clip(dest); - newclip = FC_RectIntersect(oldclip, box); - } - else - newclip = box; - set_clip(dest, &newclip); - - set_color_for_all_caches(font, effect.color); - - FC_DrawColumnFromBuffer(font, dest, box, NULL, effect.scale, effect.alignment); - - if(useClip) - set_clip(dest, &oldclip); - else - set_clip(dest, NULL); - - return box; -} - -FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) -{ - FC_Rect box = {x, y, width, 0}; - int total_height; - - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - return FC_MakeRect(box.x, box.y, width, total_height); -} - -FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...) -{ - FC_Rect box = {x, y, width, 0}; - int total_height; - - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - switch(align) - { - case FC_ALIGN_CENTER: - box.x -= width/2; - break; - case FC_ALIGN_RIGHT: - box.x -= width; - break; - default: - break; - } - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), align); - - return FC_MakeRect(box.x, box.y, width, total_height); -} - -FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...) -{ - FC_Rect box = {x, y, width, 0}; - int total_height; - - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, scale, FC_ALIGN_LEFT); - - return FC_MakeRect(box.x, box.y, width, total_height); -} - -FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...) -{ - FC_Rect box = {x, y, width, 0}; - int total_height; - - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, color); - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT); - - return FC_MakeRect(box.x, box.y, width, total_height); -} - -FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...) -{ - FC_Rect box = {x, y, width, 0}; - int total_height; - - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, effect.color); - - switch(effect.alignment) - { - case FC_ALIGN_CENTER: - box.x -= width/2; - break; - case FC_ALIGN_RIGHT: - box.x -= width; - break; - default: - break; - } - - FC_DrawColumnFromBuffer(font, dest, box, &total_height, effect.scale, effect.alignment); - - return FC_MakeRect(box.x, box.y, width, total_height); -} - -static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) -{ - FC_Rect result = {x, y, 0, 0}; - if(text == NULL || font == NULL) - return result; - - char* str = U8_strdup(text); - char* del = str; - char* c; - - // Go through str, when you find a \n, replace it with \0 and print it - // then move down, back, and continue. - for(c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result); - *c = '\n'; - c++; - str = c; - y += scale.y*font->height; - } - else - c++; - } - - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result); - - free(del); - return result; -} - -static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) -{ - FC_Rect result = {x, y, 0, 0}; - if(text == NULL || font == NULL) - return result; - - char* str = U8_strdup(text); - char* del = str; - char* c; - - for(c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result); - *c = '\n'; - c++; - str = c; - y += scale.y*font->height; - } - else - c++; - } - - result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result); - - free(del); - return result; -} - - - -FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - return FC_RenderLeft(font, dest, x, y, scale, fc_buffer); -} - -FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, font->default_color); - - FC_Rect result; - switch(align) - { - case FC_ALIGN_LEFT: - result = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - case FC_ALIGN_CENTER: - result = FC_RenderCenter(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - case FC_ALIGN_RIGHT: - result = FC_RenderRight(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); - break; - default: - result = FC_MakeRect(x, y, 0, 0); - break; - } - - return result; -} - -FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, color); - - return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer); -} - - -FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return FC_MakeRect(x, y, 0, 0); - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - set_color_for_all_caches(font, effect.color); - - FC_Rect result; - switch(effect.alignment) - { - case FC_ALIGN_LEFT: - result = FC_RenderLeft(font, dest, x, y, effect.scale, fc_buffer); - break; - case FC_ALIGN_CENTER: - result = FC_RenderCenter(font, dest, x, y, effect.scale, fc_buffer); - break; - case FC_ALIGN_RIGHT: - result = FC_RenderRight(font, dest, x, y, effect.scale, fc_buffer); - break; - default: - result = FC_MakeRect(x, y, 0, 0); - break; - } - - return result; -} - - - - -// Getters - - -FC_FilterEnum FC_GetFilterMode(FC_Font* font) -{ - if(font == NULL) - return FC_FILTER_NEAREST; - - return font->filter; -} - -Uint16 FC_GetLineHeight(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->height; -} - -Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return 0; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - Uint16 numLines = 1; - const char* c; - - for (c = fc_buffer; *c != '\0'; c++) - { - if(*c == '\n') - numLines++; - } - - // Actual height of letter region + line spacing - return font->height*numLines + font->lineSpacing*(numLines - 1); //height*numLines; -} - -Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) -{ - if(formatted_text == NULL || font == NULL) - return 0; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - const char* c; - Uint16 width = 0; - Uint16 bigWidth = 0; // Allows for multi-line strings - - for (c = fc_buffer; *c != '\0'; c++) - { - if(*c == '\n') - { - bigWidth = bigWidth >= width? bigWidth : width; - width = 0; - continue; - } - - FC_GlyphData glyph; - Uint32 codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(FC_GetGlyphData(font, &glyph, codepoint) || FC_GetGlyphData(font, &glyph, ' ')) - width += glyph.rect.w; - } - bigWidth = bigWidth >= width? bigWidth : width; - - return bigWidth; -} - -// If width == -1, use no width limit -FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...) -{ - FC_Rect result = {0, 0, 1, FC_GetLineHeight(font)}; - FC_StringList *ls, *iter; - int num_lines = 0; - Uint8 done = 0; - - if(formatted_text == NULL || column_width == 0 || position_index == 0 || font == NULL) - return result; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); - for(iter = ls; iter != NULL;) - { - char* line; - int i = 0; - FC_StringList* next_iter = iter->next; - - ++num_lines; - for(line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) - { - ++i; - --position_index; - if(position_index == 0) - { - // FIXME: Doesn't handle box-wrapped newlines correctly - line = (char*)U8_next(line); - line[0] = '\0'; - result.x = FC_GetWidth(font, "%s", iter->value); - done = 1; - break; - } - } - if(done) - break; - - // Prevent line wrapping if there are no more lines - if(next_iter == NULL && !done) - result.x = FC_GetWidth(font, "%s", iter->value); - iter = next_iter; - } - FC_StringListFree(ls); - - if(num_lines > 1) - { - result.y = (num_lines - 1) * FC_GetLineHeight(font); - } - - return result; -} - - -Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...) -{ - int y = 0; - - FC_StringList *ls, *iter; - - if(font == NULL) - return 0; - - if(formatted_text == NULL || width == 0) - return font->height; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0); - for(iter = ls; iter != NULL; iter = iter->next) - { - y += FC_GetLineHeight(font); - } - FC_StringListFree(ls); - - return y; -} - -static int FC_GetAscentFromCodepoint(FC_Font* font, Uint32 codepoint) -{ - FC_GlyphData glyph; - - if(font == NULL) - return 0; - - // FIXME: Store ascent so we can return it here - FC_GetGlyphData(font, &glyph, codepoint); - return glyph.rect.h; -} - -static int FC_GetDescentFromCodepoint(FC_Font* font, Uint32 codepoint) -{ - FC_GlyphData glyph; - - if(font == NULL) - return 0; - - // FIXME: Store descent so we can return it here - FC_GetGlyphData(font, &glyph, codepoint); - return glyph.rect.h; -} - -int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) -{ - Uint32 codepoint; - int max, ascent; - const char* c; - - if(font == NULL) - return 0; - - if(formatted_text == NULL) - return font->ascent; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - max = 0; - c = fc_buffer; - - while(*c != '\0') - { - codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(codepoint != 0) - { - ascent = FC_GetAscentFromCodepoint(font, codepoint); - if(ascent > max) - max = ascent; - } - ++c; - } - return max; -} - -int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) -{ - Uint32 codepoint; - int max, descent; - const char* c; - - if(font == NULL) - return 0; - - if(formatted_text == NULL) - return font->descent; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - max = 0; - c = fc_buffer; - - while(*c != '\0') - { - codepoint = FC_GetCodepointFromUTF8(&c, 1); - if(codepoint != 0) - { - descent = FC_GetDescentFromCodepoint(font, codepoint); - if(descent > max) - max = descent; - } - ++c; - } - return max; -} - -int FC_GetBaseline(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->baseline; -} - -int FC_GetSpacing(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->letterSpacing; -} - -int FC_GetLineSpacing(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->lineSpacing; -} - -Uint16 FC_GetMaxWidth(FC_Font* font) -{ - if(font == NULL) - return 0; - - return font->maxWidth; -} - -SDL_Color FC_GetDefaultColor(FC_Font* font) -{ - if(font == NULL) - { - SDL_Color c = {0,0,0,255}; - return c; - } - - return font->default_color; -} - - -Uint8 FC_InRect(float x, float y, FC_Rect input_rect) -{ - return (input_rect.x <= x && x <= input_rect.x + input_rect.w && input_rect.y <= y && y <= input_rect.y + input_rect.h); -} - -// TODO: Make it work with alignment -Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...) -{ - FC_StringList *ls, *iter; - Uint8 done = 0; - int height = FC_GetLineHeight(font); - Uint16 position = 0; - int current_x = 0; - int current_y = 0; - FC_GlyphData glyph_data; - - if(formatted_text == NULL || column_width == 0 || font == NULL) - return 0; - - FC_EXTRACT_VARARGS(fc_buffer, formatted_text); - - ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1); - for(iter = ls; iter != NULL; iter = iter->next) - { - char* line; - - for(line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) - { - if(FC_GetGlyphData(font, &glyph_data, FC_GetCodepointFromUTF8((const char**)&line, 0))) - { - if(FC_InRect(x, y, FC_MakeRect(current_x, current_y, glyph_data.rect.w, glyph_data.rect.h))) - { - done = 1; - break; - } - - current_x += glyph_data.rect.w; - } - position++; - } - if(done) - break; - - current_x = 0; - current_y += height; - if(y < current_y) - break; - } - FC_StringListFree(ls); - - return position; -} - - - - -// Setters - - -void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter) -{ - if(font == NULL) - return; - - if(font->filter != filter) - { - font->filter = filter; - - #ifdef FC_USE_SDL_GPU - // Update each texture to use this filter mode - { - int i; - GPU_FilterEnum gpu_filter = GPU_FILTER_NEAREST; - if(FC_GetFilterMode(font) == FC_FILTER_LINEAR) - gpu_filter = GPU_FILTER_LINEAR; - - for(i = 0; i < font->glyph_cache_count; ++i) - { - GPU_SetImageFilter(font->glyph_cache[i], gpu_filter); - } - } - #endif - } -} - - -void FC_SetSpacing(FC_Font* font, int LetterSpacing) -{ - if(font == NULL) - return; - - font->letterSpacing = LetterSpacing; -} - -void FC_SetLineSpacing(FC_Font* font, int LineSpacing) -{ - if(font == NULL) - return; - - font->lineSpacing = LineSpacing; -} - -void FC_SetDefaultColor(FC_Font* font, SDL_Color color) -{ - if(font == NULL) - return; - - font->default_color = color; -} diff --git a/source/code/Libs/SDL_FontCache.h b/source/code/Libs/SDL_FontCache.h deleted file mode 100644 index 2b7d08e..0000000 --- a/source/code/Libs/SDL_FontCache.h +++ /dev/null @@ -1,311 +0,0 @@ -/* -SDL_FontCache v0.9.0: A font cache for SDL and SDL_ttf -by Jonathan Dearborn -Dedicated to the memory of Florian Hufsky - -License: - The short: - Use it however you'd like, but keep the copyright and license notice - whenever these files or parts of them are distributed in uncompiled form. - - The long: -Copyright (c) 2016 Jonathan Dearborn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef _SDL_FONTCACHE_H__ -#define _SDL_FONTCACHE_H__ - -#include "SDL.h" -#include "SDL_ttf.h" - -#ifdef FC_USE_SDL_GPU - #include "SDL_gpu.h" -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -// Let's pretend this exists... -#define TTF_STYLE_OUTLINE 16 - - - -// Differences between SDL_Renderer and SDL_gpu -#ifdef FC_USE_SDL_GPU -#define FC_Rect GPU_Rect -#define FC_Target GPU_Target -#define FC_Image GPU_Image -#define FC_Log GPU_LogError -#else -#define FC_Rect SDL_Rect -#define FC_Target SDL_Renderer -#define FC_Image SDL_Texture -#define FC_Log SDL_Log -#endif - - -// SDL_FontCache types - -typedef enum -{ - FC_ALIGN_LEFT, - FC_ALIGN_CENTER, - FC_ALIGN_RIGHT -} FC_AlignEnum; - -typedef enum -{ - FC_FILTER_NEAREST, - FC_FILTER_LINEAR -} FC_FilterEnum; - -typedef struct FC_Scale -{ - float x; - float y; - -} FC_Scale; - -typedef struct FC_Effect -{ - FC_AlignEnum alignment; - FC_Scale scale; - SDL_Color color; - -} FC_Effect; - -// Opaque type -typedef struct FC_Font FC_Font; - - -typedef struct FC_GlyphData -{ - SDL_Rect rect; - int cache_level; - -} FC_GlyphData; - - - - -// Object creation - -FC_Rect FC_MakeRect(float x, float y, float w, float h); - -FC_Scale FC_MakeScale(float x, float y); - -SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a); - -FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color); - -FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h); - - - -// Font object - -FC_Font* FC_CreateFont(void); - -#ifdef FC_USE_SDL_GPU -Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style); - -Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color); - -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style); -#else -Uint8 FC_LoadFont(FC_Font* font, SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style); - -Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color); - -Uint8 FC_LoadFont_RW(FC_Font* font, SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style); -#endif - -void FC_ClearFont(FC_Font* font); - -void FC_FreeFont(FC_Font* font); - - - -// Built-in loading strings - -char* FC_GetStringASCII(void); - -char* FC_GetStringLatin1(void); - -char* FC_GetStringASCII_Latin1(void); - - -// UTF-8 to SDL_FontCache codepoint conversion - -/*! -Returns the Uint32 codepoint (not UTF-32) parsed from the given UTF-8 string. -\param c A pointer to a string of proper UTF-8 character values. -\param advance_pointer If true, the source pointer will be incremented to skip the extra bytes from multibyte codepoints. -*/ -Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer); - -/*! -Parses the given codepoint and stores the UTF-8 bytes in 'result'. The result is NULL terminated. -\param result A memory buffer for the UTF-8 values. Must be at least 5 bytes long. -\param codepoint The Uint32 codepoint to parse (not UTF-32). -*/ -void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint); - - -// UTF-8 string operations - -/*! Allocates a new string of 'size' bytes that is already NULL-terminated. The NULL byte counts toward the size limit, as usual. Returns NULL if size is 0. */ -char* U8_alloc(unsigned int size); - -/*! Deallocates the given string. */ -void U8_free(char* string); - -/*! Allocates a copy of the given string. */ -char* U8_strdup(const char* string); - -/*! Returns the number of UTF-8 characters in the given string. */ -int U8_strlen(const char* string); - -/*! Returns the number of bytes in the UTF-8 multibyte character pointed at by 'character'. */ -int U8_charsize(const char* character); - -/*! Copies the source multibyte character into the given buffer without overrunning it. Returns 0 on failure. */ -int U8_charcpy(char* buffer, const char* source, int buffer_size); - -/*! Returns a pointer to the next UTF-8 character. */ -const char* U8_next(const char* string); - -/*! Inserts a UTF-8 string into 'string' at the given position. Use a position of -1 to append. Returns 0 when unable to insert the string. */ -int U8_strinsert(char* string, int position, const char* source, int max_bytes); - -/*! Erases the UTF-8 character at the given position, moving the subsequent characters down. */ -void U8_strdel(char* string, int position); - - -// Internal settings - -/*! Sets the string from which to load the initial glyphs. Use this if you need upfront loading for any reason (such as lack of render-target support). */ -void FC_SetLoadingString(FC_Font* font, const char* string); - -/*! Returns the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */ -unsigned int FC_GetBufferSize(void); - -/*! Changes the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */ -void FC_SetBufferSize(unsigned int size); - -void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale)); - -FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale); - - -// Custom caching - -/*! Returns the number of cache levels that are active. */ -int FC_GetNumCacheLevels(FC_Font* font); - -/*! Returns the cache source texture at the given cache level. */ -FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level); - -// TODO: Specify ownership of the texture (should be shareable) -/*! Sets a cache source texture for rendering. New cache levels must be sequential. */ -Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture); - -/*! Copies the given surface to the given cache level as a texture. New cache levels must be sequential. */ -Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface); - - -/*! Returns the number of codepoints that are stored in the font's glyph data map. */ -unsigned int FC_GetNumCodepoints(FC_Font* font); - -/*! Copies the stored codepoints into the given array. */ -void FC_GetCodepoints(FC_Font* font, Uint32* result); - -/*! Stores the glyph data for the given codepoint in 'result'. Returns 0 if the codepoint was not found in the cache. */ -Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint); - -/*! Sets the glyph data for the given codepoint. Duplicates are not checked. Returns a pointer to the stored data. */ -FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data); - - -// Rendering - -FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...); -FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...); -FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...); -FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...); -FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...); - -FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...); -FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...); -FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...); -FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...); -FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...); - -FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...); -FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...); -FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...); -FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...); -FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...); - - -// Getters - -FC_FilterEnum FC_GetFilterMode(FC_Font* font); -Uint16 FC_GetLineHeight(FC_Font* font); -Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...); -Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...); - -// Returns a 1-pixel wide box in front of the character in the given position (index) -FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...); -Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...); - -int FC_GetAscent(FC_Font* font, const char* formatted_text, ...); -int FC_GetDescent(FC_Font* font, const char* formatted_text, ...); -int FC_GetBaseline(FC_Font* font); -int FC_GetSpacing(FC_Font* font); -int FC_GetLineSpacing(FC_Font* font); -Uint16 FC_GetMaxWidth(FC_Font* font); -SDL_Color FC_GetDefaultColor(FC_Font* font); - -Uint8 FC_InRect(float x, float y, FC_Rect input_rect); -// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index) -Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...); - -// Setters - -void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter); -void FC_SetSpacing(FC_Font* font, int LetterSpacing); -void FC_SetLineSpacing(FC_Font* font, int LineSpacing); -void FC_SetDefaultColor(FC_Font* font, SDL_Color color); - - -#ifdef __cplusplus -} -#endif - - - -#endif diff --git a/source/code/MenuSystem.h b/source/code/MenuSystem.h index dd12896..cf3016f 100644 --- a/source/code/MenuSystem.h +++ b/source/code/MenuSystem.h @@ -29,7 +29,6 @@ http://blockattack.net #include "SDL.h" #include #include -#include "Libs/NFont.h" #include "sago/SagoSprite.hpp" #include "sago/GameStateInterface.hpp" #include diff --git a/source/code/global.hpp b/source/code/global.hpp index a7b7a67..0541109 100644 --- a/source/code/global.hpp +++ b/source/code/global.hpp @@ -24,7 +24,6 @@ http://www.blockattack.net #ifndef _GLOBAL_HPP #define _GLOBAL_HPP -#include "Libs/NFont.h" #include #include "sago/SagoSpriteHolder.hpp" #include "highscore.h" diff --git a/source/code/main.cpp b/source/code/main.cpp index fa7a84c..79bbb58 100644 --- a/source/code/main.cpp +++ b/source/code/main.cpp @@ -44,7 +44,6 @@ http://www.blockattack.net #include //Used for sound & music #include //To load PNG images! #include //Abstract file system. To use containers -#include "Libs/NFont.h" #include #include "MenuSystem.h" #include "puzzlehandler.hpp"