diff --git a/source/code/BlockGame.cpp b/source/code/BlockGame.cpp index c67ecbc..bbda1ff 100644 --- a/source/code/BlockGame.cpp +++ b/source/code/BlockGame.cpp @@ -121,7 +121,7 @@ BlockGame::~BlockGame() void BlockGame::setGameSpeed(Uint8 globalSpeedLevel) { - format f("%1%"); + boost::format f("%1%"); f % globalSpeedLevel; switch (globalSpeedLevel) { @@ -148,7 +148,7 @@ void BlockGame::setGameSpeed(Uint8 globalSpeedLevel) void BlockGame::setHandicap(Uint8 globalHandicap) { - format f("%1%"); + boost::format f("%1%"); f % globalHandicap; handicap=1000*((Uint32)globalHandicap); } diff --git a/source/code/Libs/NFont.cpp b/source/code/Libs/NFont.cpp index 4522600..19108ac 100644 --- a/source/code/Libs/NFont.cpp +++ b/source/code/Libs/NFont.cpp @@ -1,1108 +1,1108 @@ -/* -NFont v2.0.0: A bitmap font class for SDL -by Jonathan Dearborn 2-4-10 -(class adapted from 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) 2010 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. -*/ -#include "NFont.h" - -char* NFont::buffer = NULL; -NFont::AnimData NFont::data; - -#define MIN(a,b) (a < b? a : b) -#define MAX(a,b) (a > b? a : b) - -// Static setters -void NFont::setAnimData(void* data) -{ - NFont::data.userVar = data; -} - -void NFont::setBuffer(unsigned int size) -{ - delete[] buffer; - if(size > 0) - buffer = new char[size]; - else - buffer = new char[1024]; -} - - -// Static functions -char* NFont::copyString(const char* c) -{ - if(c == NULL) return NULL; - - int count = 0; - for(; c[count] != '\0'; count++); - - char* result = new char[count+1]; - - for(int i = 0; i < count; i++) - { - result[i] = c[i]; - } - - result[count] = '\0'; - return result; -} - -Uint32 NFont::getPixel(SDL_Surface *Surface, int x, int y) // No Alpha? -{ - 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; // Best I could do for errors -} - -SDL_Rect NFont::rectUnion(const SDL_Rect& A, const SDL_Rect& B) -{ - Sint16 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); - SDL_Rect result = {x, y, x2 - x, y2 - y}; - return result; -} - -SDL_Surface* NFont::copySurface(SDL_Surface *Surface) -{ - return SDL_ConvertSurface(Surface, Surface->format, Surface->flags); -} - -SDL_Surface* NFont::verticalGradient(SDL_Surface* targetSurface, Uint32 top, Uint32 bottom, int heightAdjust) -{ - SDL_Surface* surface = targetSurface; - if(surface == NULL) - return NULL; - - Uint8 tr, tg, tb; - - SDL_GetRGB(top, surface->format, &tr, &tg, &tb); - - Uint8 br, bg, bb; - - SDL_GetRGB(bottom, surface->format, &br, &bg, &bb); - - bool useCK = (surface->flags & SDL_SRCALPHA) != SDL_SRCALPHA; // colorkey if no alpha - Uint32 colorkey = surface->format->colorkey; - - Uint8 r, g, b, a; - float ratio; - Uint32 color; - int temp; - - for (int x = 0, y = 0; y < surface->h; x++) - { - if (x >= surface->w) - { - x = 0; - y++; - - if (y >= surface->h) - break; - } - - ratio = (y - 2)/float(surface->h - heightAdjust); // the neg 3s are for full color at top and bottom - - if(!useCK) - { - color = getPixel(surface, x, y); - SDL_GetRGBA(color, surface->format, &r, &g, &b, &a); // just getting alpha - } - else - a = SDL_ALPHA_OPAQUE; - - // Get and clamp the new values - temp = int(tr*(1-ratio) + br*ratio); - r = temp < 0? 0 : temp > 255? 255 : temp; - - temp = int(tg*(1-ratio) + bg*ratio); - g = temp < 0? 0 : temp > 255? 255 : temp; - - temp = int(tb*(1-ratio) + bb*ratio); - b = temp < 0? 0 : temp > 255? 255 : temp; - - - color = SDL_MapRGBA(surface->format, r, g, b, a); - - - if(useCK) - { - if(getPixel(surface, x, y) == colorkey) - continue; - if(color == colorkey) - color == 0? color++ : color--; - } - - // make sure it isn't pink - if(color == SDL_MapRGBA(surface->format, 0xFF, 0, 0xFF, a)) - color--; - if(getPixel(surface, x, y) == SDL_MapRGBA(surface->format, 0xFF, 0, 0xFF, SDL_ALPHA_OPAQUE)) - continue; - - 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 */ - { - 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; - } - - } - return surface; -} - - -// Constructors -NFont::NFont() -{ - init(); -} - -NFont::NFont(SDL_Surface* src) -{ - init(); - load(src); -} - -NFont::NFont(SDL_Surface* dest, SDL_Surface* src) -{ - init(); - load(src); - setDest(dest); -} - -#ifdef NFONT_USE_TTF -NFont::NFont(TTF_Font* ttf, SDL_Color fg) -{ - init(); - load(ttf, fg); -} -NFont::NFont(TTF_Font* ttf, SDL_Color fg, SDL_Color bg) -{ - init(); - load(ttf, fg, bg); -} -NFont::NFont(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) -{ - init(); - load(filename_ttf, pointSize, fg, style); -} -NFont::NFont(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) -{ - init(); - load(filename_ttf, pointSize, fg, bg, style); -} - -NFont::NFont(SDL_Surface* dest, TTF_Font* ttf, SDL_Color fg) -{ - init(); - load(ttf, fg); - setDest(dest); -} -NFont::NFont(SDL_Surface* dest, TTF_Font* ttf, SDL_Color fg, SDL_Color bg) -{ - init(); - load(ttf, fg, bg); - setDest(dest); -} -NFont::NFont(SDL_Surface* dest, const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) -{ - init(); - load(filename_ttf, pointSize, fg, style); - setDest(dest); -} -NFont::NFont(SDL_Surface* dest, const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) -{ - init(); - load(filename_ttf, pointSize, fg, bg, style); - setDest(dest); -} -#endif - -void NFont::init() -{ - src = NULL; - dest = NULL; - - maxPos = 0; - - height = 0; // ascent+descent - - maxWidth = 0; - baseline = 0; - ascent = 0; - descent = 0; - - lineSpacing = 0; - letterSpacing = 0; - - if(buffer == NULL) - buffer = new char[1024]; -} - -NFont::~NFont() -{} - - -// Loading -bool NFont::load(SDL_Surface* FontSurface) -{ - src = FontSurface; - if (src == NULL) - { - printf("\n ERROR: NFont given a NULL surface\n"); - return false; - } - - int x = 1, i = 0; - - // memset would be faster - for(int j = 0; j < 256; j++) - { - charWidth[j] = 0; - charPos[j] = 0; - } - - SDL_LockSurface(src); - - Uint32 pixel = SDL_MapRGB(src->format, 255, 0, 255); // pink pixel - - maxWidth = 0; - - // Get the character positions and widths - while (x < src->w) - { - if(getPixel(src, x, 0) != pixel) - { - charPos[i] = x; - charWidth[i] = x; - while(x < src->w && getPixel(src, x, 0) != pixel) - x++; - charWidth[i] = x - charWidth[i]; - if(charWidth[i] > maxWidth) - maxWidth = charWidth[i]; - i++; - } - - x++; - } - - maxPos = x - 1; - - - pixel = getPixel(src, 0, src->h - 1); - int j; - setBaseline(); - - // Get the max ascent - j = 1; - while(j < baseline && j < src->h) - { - x = 0; - while(x < src->w) - { - if(getPixel(src, x, j) != pixel) - { - ascent = baseline - j; - j = src->h; - break; - } - x++; - } - j++; - } - - // Get the max descent - j = src->h - 1; - while(j > 0 && j > baseline) - { - x = 0; - while(x < src->w) - { - if(getPixel(src, x, j) != pixel) - { - descent = j - baseline+1; - j = 0; - break; - } - x++; - } - j--; - } - - - height = ascent + descent; - - - if((src->flags & SDL_SRCALPHA) != SDL_SRCALPHA) - { - pixel = getPixel(src, 0, src->h - 1); - SDL_UnlockSurface(src); - SDL_SetColorKey(src, SDL_SRCCOLORKEY, pixel); - } - else - SDL_UnlockSurface(src); - - return true; -} - -bool NFont::load(SDL_Surface* destSurface, SDL_Surface* FontSurface) -{ - setDest(destSurface); - return load(FontSurface); -} - -#ifdef NFONT_USE_TTF -bool NFont::load(TTF_Font* ttf, SDL_Color fg, SDL_Color bg) -{ - if(ttf == NULL) - return false; - SDL_Surface* surfs[127 - 33]; - int width = 0; - int height = 0; - - char buff[2]; - buff[1] = '\0'; - for(int i = 0; i < 127 - 33; i++) - { - buff[0] = i + 33; - surfs[i] = TTF_RenderText_Shaded(ttf, buff, fg, bg); - width += surfs[i]->w; - height = (height < surfs[i]->h)? surfs[i]->h : height; - } - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,24, 0xFF0000, 0x00FF00, 0x0000FF, 0); -#else - SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,24, 0x0000FF, 0x00FF00, 0xFF0000, 0); -#endif - Uint32 pink = SDL_MapRGB(result->format, 255, 0, 255); - Uint32 bgcolor = SDL_MapRGB(result->format, bg.r, bg.g, bg.b); - - SDL_Rect pixel = {1, 0, 1, 1}; - SDL_Rect line = {1, 0, 1, result->h}; - - int x = 1; - SDL_Rect dest = {x, 0, 0, 0}; - for(int i = 0; i < 127 - 33; i++) - { - pixel.x = line.x = x-1; - SDL_FillRect(result, &line, bgcolor); - SDL_FillRect(result, &pixel, pink); - - SDL_BlitSurface(surfs[i], NULL, result, &dest); - - x += surfs[i]->w + 1; - dest.x = x; - - SDL_FreeSurface(surfs[i]); - } - pixel.x = line.x = x-1; - SDL_FillRect(result, &line, bgcolor); - SDL_FillRect(result, &pixel, pink); - - return load(result); -} - - -bool NFont::load(TTF_Font* ttf, SDL_Color fg) -{ - if(ttf == NULL) - return false; - SDL_Surface* surfs[127 - 33]; - int width = 0; - int height = 0; - - char buff[2]; - buff[1] = '\0'; - for(int i = 0; i < 127 - 33; i++) - { - buff[0] = i + 33; - surfs[i] = TTF_RenderText_Blended(ttf, buff, fg); - width += surfs[i]->w; - height = (height < surfs[i]->h)? surfs[i]->h : height; - } - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); -#else - SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); -#endif - Uint32 pink = SDL_MapRGBA(result->format, 255, 0, 255, SDL_ALPHA_OPAQUE); - - SDL_SetAlpha(result, 0, SDL_ALPHA_OPAQUE); - - SDL_Rect pixel = {1, 0, 1, 1}; - - int x = 1; - SDL_Rect dest = {x, 0, 0, 0}; - for(int i = 0; i < 127 - 33; i++) - { - pixel.x = x-1; - SDL_FillRect(result, &pixel, pink); - - SDL_SetAlpha(surfs[i], 0, SDL_ALPHA_OPAQUE); - SDL_BlitSurface(surfs[i], NULL, result, &dest); - - x += surfs[i]->w + 1; - dest.x = x; - - SDL_FreeSurface(surfs[i]); - } - pixel.x = x-1; - SDL_FillRect(result, &pixel, pink); - - SDL_SetAlpha(result, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); - - return load(result); -} - - -bool NFont::load(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) -{ - if(!TTF_WasInit() && TTF_Init() < 0) - { - printf("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); - return false; - } - - TTF_Font* ttf = TTF_OpenFont(filename_ttf, pointSize); - - if(ttf == NULL) - { - printf("Unable to load TrueType font: %s \n", TTF_GetError()); - return false; - } - TTF_SetFontStyle(ttf, style); - bool result = load(ttf, fg); - TTF_CloseFont(ttf); - return result; -} - -bool NFont::load(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) -{ - if(!TTF_WasInit() && TTF_Init() < 0) - { - printf("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); - return false; - } - - TTF_Font* ttf = TTF_OpenFont(filename_ttf, pointSize); - - if(ttf == NULL) - { - printf("Unable to load TrueType font: %s \n", TTF_GetError()); - return false; - } - TTF_SetFontStyle(ttf, style); - bool result = load(ttf, fg, bg); - TTF_CloseFont(ttf); - return result; -} - -#endif - - - -void NFont::freeSurface() -{ - SDL_FreeSurface(src); -} - - - -// Drawing -SDL_Rect NFont::drawToSurface(int x, int y, const char* text) const -{ - const char* c = text; - unsigned char num; - SDL_Rect srcRect, dstRect, copyS, copyD; - data.dirtyRect = makeRect(x, y, 0, 0); - - if(c == NULL || src == NULL || dest == NULL) - return data.dirtyRect; - - srcRect.y = baseline - ascent; - srcRect.h = dstRect.h = height; - dstRect.x = x; - dstRect.y = y; - - int newlineX = x; - - for(; *c != '\0'; c++) - { - if(*c == '\n') - { - dstRect.x = newlineX; - dstRect.y += height + lineSpacing; - continue; - } - - if (*c == ' ') - { - dstRect.x += charWidth[0] + letterSpacing; - continue; - } - unsigned char ctest = (unsigned char)(*c); - // Skip bad characters - if(ctest < 33 || (ctest > 126 && ctest < 161)) - continue; - if(dstRect.x >= dest->w) - continue; - if(dstRect.y >= dest->h) - continue; - - num = ctest - 33; // Get array index - if(num > 126) // shift the extended characters down to the correct index - num -= 34; - srcRect.x = charPos[num]; - srcRect.w = dstRect.w = charWidth[num]; - copyS = srcRect; - copyD = dstRect; - SDL_BlitSurface(src, &srcRect, dest, &dstRect); - if(data.dirtyRect.w == 0 || data.dirtyRect.h == 0) - data.dirtyRect = dstRect; - else - data.dirtyRect = rectUnion(data.dirtyRect, dstRect); - srcRect = copyS; - dstRect = copyD; - - dstRect.x += dstRect.w + letterSpacing; - } - - return data.dirtyRect; -} - -SDL_Rect NFont::drawToSurfacePos(int x, int y, NFont::AnimFn posFn) const -{ - data.font = this; - data.dest = dest; - data.src = src; - data.text = buffer; // Buffer for efficient drawing - data.height = height; - data.charPos = charPos; - data.charWidth = charWidth; - data.maxX = maxPos; - data.dirtyRect = makeRect(x,y,0,0); - - data.index = -1; - data.letterNum = 0; - data.wordNum = 1; - data.lineNum = 1; - data.startX = x; // used as reset value for line feed - data.startY = y; - - int preFnX = x; - int preFnY = y; - - const char* c = buffer; - unsigned char num; - SDL_Rect srcRect, dstRect, copyS, copyD; - - if(c == NULL || src == NULL || dest == NULL) - return makeRect(x,y,0,0); - - srcRect.y = baseline - ascent; - srcRect.h = dstRect.h = height; - dstRect.x = x; - dstRect.y = y; - - for(; *c != '\0'; c++) - { - data.index++; - data.letterNum++; - - if(*c == '\n') - { - data.letterNum = 1; - data.wordNum = 1; - data.lineNum++; - - x = data.startX; // carriage return - y += height + lineSpacing; - continue; - } - if (*c == ' ') - { - data.letterNum = 1; - data.wordNum++; - - x += charWidth[0] + letterSpacing; - continue; - } - unsigned char ctest = (unsigned char)(*c); - // Skip bad characters - if(ctest < 33 || (ctest > 126 && ctest < 161)) - continue; - //if(x >= dest->w) // This shouldn't be used with position control - // continue; - num = ctest - 33; - if(num > 126) // shift the extended characters down to the array index - num -= 34; - srcRect.x = charPos[num]; - srcRect.w = dstRect.w = charWidth[num]; - - preFnX = x; // Save real position - preFnY = y; - - // Use function pointer to get final x, y values - posFn(x, y, data); - - dstRect.x = x; - dstRect.y = y; - - copyS = srcRect; - copyD = dstRect; - SDL_BlitSurface(src, &srcRect, dest, &dstRect); - if(data.dirtyRect.w == 0 || data.dirtyRect.h == 0) - data.dirtyRect = dstRect; - else - data.dirtyRect = rectUnion(data.dirtyRect, dstRect); - srcRect = copyS; - dstRect = copyD; - - x = preFnX; // Restore real position - y = preFnY; - - x += dstRect.w + letterSpacing; - } - - return data.dirtyRect; -} - -SDL_Rect NFont::draw(int x, int y, const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return makeRect(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - return drawToSurface(x, y, buffer); -} - -SDL_Rect NFont::drawCenter(int x, int y, const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return makeRect(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - char* str = copyString(buffer); - char* del = str; - - // Go through str, when you find a \n, replace it with \0 and print it - // then move down, back, and continue. - for(char* c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - drawToSurface(x - getWidth("%s", str)/2, y, str); - *c = '\n'; - c++; - str = c; - y += height; - } - else - c++; - } - char s[strlen(str)+1]; - strcpy(s, str); - delete[] del; - - return drawToSurface(x - getWidth("%s", s)/2, y, s); -} - -SDL_Rect NFont::drawRight(int x, int y, const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return makeRect(x, y, 0, 0); - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - char* str = copyString(buffer); - char* del = str; - - for(char* c = str; *c != '\0';) - { - if(*c == '\n') - { - *c = '\0'; - drawToSurface(x - getWidth("%s", str), y, str); - *c = '\n'; - c++; - str = c; - y += height; - } - else - c++; - } - char s[strlen(str)+1]; - strcpy(s, str); - delete[] del; - - return drawToSurface(x - getWidth("%s", s), y, s); -} - -SDL_Rect NFont::drawPos(int x, int y, NFont::AnimFn posFn, const char* text, ...) const -{ - va_list lst; - va_start(lst, text); - vsprintf(buffer, text, lst); - va_end(lst); - - return drawToSurfacePos(x, y, posFn); -} - -SDL_Rect NFont::drawAll(int x, int y, NFont::AnimFn allFn, const char* text, ...) const -{ - va_list lst; - va_start(lst, text); - vsprintf(buffer, text, lst); - va_end(lst); - - allFn(x, y, data); - return data.dirtyRect; -} - - - - -// Getters -SDL_Surface* NFont::getDest() const -{ - return dest; -} - -SDL_Surface* NFont::getSurface() const -{ - return src; -} - -int NFont::getHeight(const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return height; - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - int numLines = 1; - const char* c; - - for (c = buffer; *c != '\0'; c++) - { - if(*c == '\n') - numLines++; - } - - // Actual height of letter region + line spacing - return height*numLines + lineSpacing*(numLines - 1); //height*numLines; -} - -int NFont::getWidth(const char* formatted_text, ...) const -{ - if (formatted_text == NULL) - return 0; - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - const char* c; - int charnum = 0; - int width = 0; - int bigWidth = 0; // Allows for multi-line strings - - for (c = buffer; *c != '\0'; c++) - { - charnum = (unsigned char)(*c) - 33; - - // skip spaces and nonprintable characters - if(*c == '\n') - { - bigWidth = bigWidth >= width? bigWidth : width; - width = 0; - } - else if (*c == ' ' || charnum > 222) - { - width += charWidth[0]; - continue; - } - - width += charWidth[charnum]; - } - bigWidth = bigWidth >= width? bigWidth : width; - - return bigWidth; -} - -int NFont::getAscent(const char character) const -{ - unsigned char test = (unsigned char)character; - if(test < 33 || test > 222 || (test > 126 && test < 161)) - return 0; - unsigned char num = (unsigned char)character - 33; - // Get the max ascent - int x = charPos[num]; - int i, j = 1, result = 0; - Uint32 pixel = getPixel(src, 0, src->h - 1); // bg pixel - while(j < baseline && j < src->h) - { - i = charPos[num]; - while(i < x + charWidth[num]) - { - if(getPixel(src, i, j) != pixel) - { - result = baseline - j; - j = src->h; - break; - } - i++; - } - j++; - } - return result; -} - -int NFont::getAscent(const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return ascent; - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - int max = 0; - const char* c = buffer; - - for (; *c != '\0'; c++) - { - int asc = getAscent(*c); - if(asc > max) - max = asc; - } - return max; -} - -int NFont::getDescent(const char character) const -{ - unsigned char test = (unsigned char)character; - if(test < 33 || test > 222 || (test > 126 && test < 161)) - return 0; - unsigned char num = (unsigned char)character - 33; - // Get the max descent - int x = charPos[num]; - int i, j = src->h - 1, result = 0; - Uint32 pixel = getPixel(src, 0, src->h - 1); // bg pixel - while(j > 0 && j > baseline) - { - i = charPos[num]; - while(i < x + charWidth[num]) - { - if(getPixel(src, i, j) != pixel) - { - result = j - baseline; - j = 0; - break; - } - i++; - } - j--; - } - return result; -} - -int NFont::getDescent(const char* formatted_text, ...) const -{ - if(formatted_text == NULL) - return descent; - - va_list lst; - va_start(lst, formatted_text); - vsprintf(buffer, formatted_text, lst); - va_end(lst); - - int max = 0; - const char* c = buffer; - - for (; *c != '\0'; c++) - { - int des = getDescent(*c); - if(des > max) - max = des; - } - return max; -} - -int NFont::getSpacing() const -{ - return letterSpacing; -} - -int NFont::getLineSpacing() const -{ - return lineSpacing; -} - -int NFont::getBaseline() const -{ - return baseline; -} - -int NFont::getMaxWidth() const -{ - return maxWidth; -} - - - - - -// Setters -void NFont::setSpacing(int LetterSpacing) -{ - letterSpacing = LetterSpacing; -} - -void NFont::setLineSpacing(int LineSpacing) -{ - lineSpacing = LineSpacing; -} - -void NFont::setDest(SDL_Surface* Dest) -{ - dest = Dest; -} - -int NFont::setBaseline(int Baseline) -{ - if(Baseline >= 0) - baseline = Baseline; - else - { - // Get the baseline by checking a, b, and c and averaging their lowest y-value. - // Is there a better way? - Uint32 pixel = getPixel(src, 0, src->h - 1); - int heightSum = 0; - int x, i, j; - for(unsigned char avgChar = 64; avgChar < 67; avgChar++) - { - x = charPos[avgChar]; - - j = src->h - 1; - while(j > 0) - { - i = x; - while(i - x < charWidth[64]) - { - if(getPixel(src, i, j) != pixel) - { - heightSum += j; - j = 0; - break; - } - i++; - } - j--; - } - } - baseline = int(heightSum/3.0f + 0.5f); // Round up and cast - } - return baseline; -} - - - - - - - +/* +NFont v2.0.0: A bitmap font class for SDL +by Jonathan Dearborn 2-4-10 +(class adapted from 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) 2010 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. +*/ +#include "NFont.h" + +char* NFont::buffer = NULL; +NFont::AnimData NFont::data; + +#define MIN(a,b) (a < b? a : b) +#define MAX(a,b) (a > b? a : b) + +// Static setters +void NFont::setAnimData(void* data) +{ + NFont::data.userVar = data; +} + +void NFont::setBuffer(unsigned int size) +{ + delete[] buffer; + if(size > 0) + buffer = new char[size]; + else + buffer = new char[1024]; +} + + +// Static functions +char* NFont::copyString(const char* c) +{ + if(c == NULL) return NULL; + + int count = 0; + for(; c[count] != '\0'; count++); + + char* result = new char[count+1]; + + for(int i = 0; i < count; i++) + { + result[i] = c[i]; + } + + result[count] = '\0'; + return result; +} + +Uint32 NFont::getPixel(SDL_Surface *Surface, int x, int y) // No Alpha? +{ + 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; // Best I could do for errors +} + +SDL_Rect NFont::rectUnion(const SDL_Rect& A, const SDL_Rect& B) +{ + Sint16 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); + SDL_Rect result = {static_cast(x), static_cast(y), static_cast(x2 - x), static_cast(y2 - y)}; + return result; +} + +SDL_Surface* NFont::copySurface(SDL_Surface *Surface) +{ + return SDL_ConvertSurface(Surface, Surface->format, Surface->flags); +} + +SDL_Surface* NFont::verticalGradient(SDL_Surface* targetSurface, Uint32 top, Uint32 bottom, int heightAdjust) +{ + SDL_Surface* surface = targetSurface; + if(surface == NULL) + return NULL; + + Uint8 tr, tg, tb; + + SDL_GetRGB(top, surface->format, &tr, &tg, &tb); + + Uint8 br, bg, bb; + + SDL_GetRGB(bottom, surface->format, &br, &bg, &bb); + + bool useCK = (surface->flags & SDL_SRCALPHA) != SDL_SRCALPHA; // colorkey if no alpha + Uint32 colorkey = surface->format->colorkey; + + Uint8 r, g, b, a; + float ratio; + Uint32 color; + int temp; + + for (int x = 0, y = 0; y < surface->h; x++) + { + if (x >= surface->w) + { + x = 0; + y++; + + if (y >= surface->h) + break; + } + + ratio = (y - 2)/float(surface->h - heightAdjust); // the neg 3s are for full color at top and bottom + + if(!useCK) + { + color = getPixel(surface, x, y); + SDL_GetRGBA(color, surface->format, &r, &g, &b, &a); // just getting alpha + } + else + a = SDL_ALPHA_OPAQUE; + + // Get and clamp the new values + temp = int(tr*(1-ratio) + br*ratio); + r = temp < 0? 0 : temp > 255? 255 : temp; + + temp = int(tg*(1-ratio) + bg*ratio); + g = temp < 0? 0 : temp > 255? 255 : temp; + + temp = int(tb*(1-ratio) + bb*ratio); + b = temp < 0? 0 : temp > 255? 255 : temp; + + + color = SDL_MapRGBA(surface->format, r, g, b, a); + + + if(useCK) + { + if(getPixel(surface, x, y) == colorkey) + continue; + if(color == colorkey) + color == 0? color++ : color--; + } + + // make sure it isn't pink + if(color == SDL_MapRGBA(surface->format, 0xFF, 0, 0xFF, a)) + color--; + if(getPixel(surface, x, y) == SDL_MapRGBA(surface->format, 0xFF, 0, 0xFF, SDL_ALPHA_OPAQUE)) + continue; + + 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 */ + { + 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; + } + + } + return surface; +} + + +// Constructors +NFont::NFont() +{ + init(); +} + +NFont::NFont(SDL_Surface* src) +{ + init(); + load(src); +} + +NFont::NFont(SDL_Surface* dest, SDL_Surface* src) +{ + init(); + load(src); + setDest(dest); +} + +#ifdef NFONT_USE_TTF +NFont::NFont(TTF_Font* ttf, SDL_Color fg) +{ + init(); + load(ttf, fg); +} +NFont::NFont(TTF_Font* ttf, SDL_Color fg, SDL_Color bg) +{ + init(); + load(ttf, fg, bg); +} +NFont::NFont(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) +{ + init(); + load(filename_ttf, pointSize, fg, style); +} +NFont::NFont(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) +{ + init(); + load(filename_ttf, pointSize, fg, bg, style); +} + +NFont::NFont(SDL_Surface* dest, TTF_Font* ttf, SDL_Color fg) +{ + init(); + load(ttf, fg); + setDest(dest); +} +NFont::NFont(SDL_Surface* dest, TTF_Font* ttf, SDL_Color fg, SDL_Color bg) +{ + init(); + load(ttf, fg, bg); + setDest(dest); +} +NFont::NFont(SDL_Surface* dest, const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) +{ + init(); + load(filename_ttf, pointSize, fg, style); + setDest(dest); +} +NFont::NFont(SDL_Surface* dest, const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) +{ + init(); + load(filename_ttf, pointSize, fg, bg, style); + setDest(dest); +} +#endif + +void NFont::init() +{ + src = NULL; + dest = NULL; + + maxPos = 0; + + height = 0; // ascent+descent + + maxWidth = 0; + baseline = 0; + ascent = 0; + descent = 0; + + lineSpacing = 0; + letterSpacing = 0; + + if(buffer == NULL) + buffer = new char[1024]; +} + +NFont::~NFont() +{} + + +// Loading +bool NFont::load(SDL_Surface* FontSurface) +{ + src = FontSurface; + if (src == NULL) + { + printf("\n ERROR: NFont given a NULL surface\n"); + return false; + } + + int x = 1, i = 0; + + // memset would be faster + for(int j = 0; j < 256; j++) + { + charWidth[j] = 0; + charPos[j] = 0; + } + + SDL_LockSurface(src); + + Uint32 pixel = SDL_MapRGB(src->format, 255, 0, 255); // pink pixel + + maxWidth = 0; + + // Get the character positions and widths + while (x < src->w) + { + if(getPixel(src, x, 0) != pixel) + { + charPos[i] = x; + charWidth[i] = x; + while(x < src->w && getPixel(src, x, 0) != pixel) + x++; + charWidth[i] = x - charWidth[i]; + if(charWidth[i] > maxWidth) + maxWidth = charWidth[i]; + i++; + } + + x++; + } + + maxPos = x - 1; + + + pixel = getPixel(src, 0, src->h - 1); + int j; + setBaseline(); + + // Get the max ascent + j = 1; + while(j < baseline && j < src->h) + { + x = 0; + while(x < src->w) + { + if(getPixel(src, x, j) != pixel) + { + ascent = baseline - j; + j = src->h; + break; + } + x++; + } + j++; + } + + // Get the max descent + j = src->h - 1; + while(j > 0 && j > baseline) + { + x = 0; + while(x < src->w) + { + if(getPixel(src, x, j) != pixel) + { + descent = j - baseline+1; + j = 0; + break; + } + x++; + } + j--; + } + + + height = ascent + descent; + + + if((src->flags & SDL_SRCALPHA) != SDL_SRCALPHA) + { + pixel = getPixel(src, 0, src->h - 1); + SDL_UnlockSurface(src); + SDL_SetColorKey(src, SDL_SRCCOLORKEY, pixel); + } + else + SDL_UnlockSurface(src); + + return true; +} + +bool NFont::load(SDL_Surface* destSurface, SDL_Surface* FontSurface) +{ + setDest(destSurface); + return load(FontSurface); +} + +#ifdef NFONT_USE_TTF +bool NFont::load(TTF_Font* ttf, SDL_Color fg, SDL_Color bg) +{ + if(ttf == NULL) + return false; + SDL_Surface* surfs[127 - 33]; + int width = 0; + int height = 0; + + char buff[2]; + buff[1] = '\0'; + for(int i = 0; i < 127 - 33; i++) + { + buff[0] = i + 33; + surfs[i] = TTF_RenderText_Shaded(ttf, buff, fg, bg); + width += surfs[i]->w; + height = (height < surfs[i]->h)? surfs[i]->h : height; + } + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,24, 0xFF0000, 0x00FF00, 0x0000FF, 0); +#else + SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,24, 0x0000FF, 0x00FF00, 0xFF0000, 0); +#endif + Uint32 pink = SDL_MapRGB(result->format, 255, 0, 255); + Uint32 bgcolor = SDL_MapRGB(result->format, bg.r, bg.g, bg.b); + + SDL_Rect pixel = {1, 0, 1, 1}; + SDL_Rect line = {1, 0, 1, static_cast(result->h)}; + + int x = 1; + SDL_Rect dest = {static_cast(x), 0, 0, 0}; + for(int i = 0; i < 127 - 33; i++) + { + pixel.x = line.x = x-1; + SDL_FillRect(result, &line, bgcolor); + SDL_FillRect(result, &pixel, pink); + + SDL_BlitSurface(surfs[i], NULL, result, &dest); + + x += surfs[i]->w + 1; + dest.x = x; + + SDL_FreeSurface(surfs[i]); + } + pixel.x = line.x = x-1; + SDL_FillRect(result, &line, bgcolor); + SDL_FillRect(result, &pixel, pink); + + return load(result); +} + + +bool NFont::load(TTF_Font* ttf, SDL_Color fg) +{ + if(ttf == NULL) + return false; + SDL_Surface* surfs[127 - 33]; + int width = 0; + int height = 0; + + char buff[2]; + buff[1] = '\0'; + for(int i = 0; i < 127 - 33; i++) + { + buff[0] = i + 33; + surfs[i] = TTF_RenderText_Blended(ttf, buff, fg); + width += surfs[i]->w; + height = (height < surfs[i]->h)? surfs[i]->h : height; + } + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); +#else + SDL_Surface* result = SDL_CreateRGBSurface(SDL_SWSURFACE,width + 127 - 33 + 1,height,32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); +#endif + Uint32 pink = SDL_MapRGBA(result->format, 255, 0, 255, SDL_ALPHA_OPAQUE); + + SDL_SetAlpha(result, 0, SDL_ALPHA_OPAQUE); + + SDL_Rect pixel = {1, 0, 1, 1}; + + int x = 1; + SDL_Rect dest = {static_cast(x), 0, 0, 0}; + for(int i = 0; i < 127 - 33; i++) + { + pixel.x = x-1; + SDL_FillRect(result, &pixel, pink); + + SDL_SetAlpha(surfs[i], 0, SDL_ALPHA_OPAQUE); + SDL_BlitSurface(surfs[i], NULL, result, &dest); + + x += surfs[i]->w + 1; + dest.x = x; + + SDL_FreeSurface(surfs[i]); + } + pixel.x = x-1; + SDL_FillRect(result, &pixel, pink); + + SDL_SetAlpha(result, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); + + return load(result); +} + + +bool NFont::load(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, int style) +{ + if(!TTF_WasInit() && TTF_Init() < 0) + { + printf("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); + return false; + } + + TTF_Font* ttf = TTF_OpenFont(filename_ttf, pointSize); + + if(ttf == NULL) + { + printf("Unable to load TrueType font: %s \n", TTF_GetError()); + return false; + } + TTF_SetFontStyle(ttf, style); + bool result = load(ttf, fg); + TTF_CloseFont(ttf); + return result; +} + +bool NFont::load(const char* filename_ttf, Uint32 pointSize, SDL_Color fg, SDL_Color bg, int style) +{ + if(!TTF_WasInit() && TTF_Init() < 0) + { + printf("Unable to initialize SDL_ttf: %s \n", TTF_GetError()); + return false; + } + + TTF_Font* ttf = TTF_OpenFont(filename_ttf, pointSize); + + if(ttf == NULL) + { + printf("Unable to load TrueType font: %s \n", TTF_GetError()); + return false; + } + TTF_SetFontStyle(ttf, style); + bool result = load(ttf, fg, bg); + TTF_CloseFont(ttf); + return result; +} + +#endif + + + +void NFont::freeSurface() +{ + SDL_FreeSurface(src); +} + + + +// Drawing +SDL_Rect NFont::drawToSurface(int x, int y, const char* text) const +{ + const char* c = text; + unsigned char num; + SDL_Rect srcRect, dstRect, copyS, copyD; + data.dirtyRect = makeRect(x, y, 0, 0); + + if(c == NULL || src == NULL || dest == NULL) + return data.dirtyRect; + + srcRect.y = baseline - ascent; + srcRect.h = dstRect.h = height; + dstRect.x = x; + dstRect.y = y; + + int newlineX = x; + + for(; *c != '\0'; c++) + { + if(*c == '\n') + { + dstRect.x = newlineX; + dstRect.y += height + lineSpacing; + continue; + } + + if (*c == ' ') + { + dstRect.x += charWidth[0] + letterSpacing; + continue; + } + unsigned char ctest = (unsigned char)(*c); + // Skip bad characters + if(ctest < 33 || (ctest > 126 && ctest < 161)) + continue; + if(dstRect.x >= dest->w) + continue; + if(dstRect.y >= dest->h) + continue; + + num = ctest - 33; // Get array index + if(num > 126) // shift the extended characters down to the correct index + num -= 34; + srcRect.x = charPos[num]; + srcRect.w = dstRect.w = charWidth[num]; + copyS = srcRect; + copyD = dstRect; + SDL_BlitSurface(src, &srcRect, dest, &dstRect); + if(data.dirtyRect.w == 0 || data.dirtyRect.h == 0) + data.dirtyRect = dstRect; + else + data.dirtyRect = rectUnion(data.dirtyRect, dstRect); + srcRect = copyS; + dstRect = copyD; + + dstRect.x += dstRect.w + letterSpacing; + } + + return data.dirtyRect; +} + +SDL_Rect NFont::drawToSurfacePos(int x, int y, NFont::AnimFn posFn) const +{ + data.font = this; + data.dest = dest; + data.src = src; + data.text = buffer; // Buffer for efficient drawing + data.height = height; + data.charPos = charPos; + data.charWidth = charWidth; + data.maxX = maxPos; + data.dirtyRect = makeRect(x,y,0,0); + + data.index = -1; + data.letterNum = 0; + data.wordNum = 1; + data.lineNum = 1; + data.startX = x; // used as reset value for line feed + data.startY = y; + + int preFnX = x; + int preFnY = y; + + const char* c = buffer; + unsigned char num; + SDL_Rect srcRect, dstRect, copyS, copyD; + + if(c == NULL || src == NULL || dest == NULL) + return makeRect(x,y,0,0); + + srcRect.y = baseline - ascent; + srcRect.h = dstRect.h = height; + dstRect.x = x; + dstRect.y = y; + + for(; *c != '\0'; c++) + { + data.index++; + data.letterNum++; + + if(*c == '\n') + { + data.letterNum = 1; + data.wordNum = 1; + data.lineNum++; + + x = data.startX; // carriage return + y += height + lineSpacing; + continue; + } + if (*c == ' ') + { + data.letterNum = 1; + data.wordNum++; + + x += charWidth[0] + letterSpacing; + continue; + } + unsigned char ctest = (unsigned char)(*c); + // Skip bad characters + if(ctest < 33 || (ctest > 126 && ctest < 161)) + continue; + //if(x >= dest->w) // This shouldn't be used with position control + // continue; + num = ctest - 33; + if(num > 126) // shift the extended characters down to the array index + num -= 34; + srcRect.x = charPos[num]; + srcRect.w = dstRect.w = charWidth[num]; + + preFnX = x; // Save real position + preFnY = y; + + // Use function pointer to get final x, y values + posFn(x, y, data); + + dstRect.x = x; + dstRect.y = y; + + copyS = srcRect; + copyD = dstRect; + SDL_BlitSurface(src, &srcRect, dest, &dstRect); + if(data.dirtyRect.w == 0 || data.dirtyRect.h == 0) + data.dirtyRect = dstRect; + else + data.dirtyRect = rectUnion(data.dirtyRect, dstRect); + srcRect = copyS; + dstRect = copyD; + + x = preFnX; // Restore real position + y = preFnY; + + x += dstRect.w + letterSpacing; + } + + return data.dirtyRect; +} + +SDL_Rect NFont::draw(int x, int y, const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return makeRect(x, y, 0, 0); + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + return drawToSurface(x, y, buffer); +} + +SDL_Rect NFont::drawCenter(int x, int y, const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return makeRect(x, y, 0, 0); + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + char* str = copyString(buffer); + char* del = str; + + // Go through str, when you find a \n, replace it with \0 and print it + // then move down, back, and continue. + for(char* c = str; *c != '\0';) + { + if(*c == '\n') + { + *c = '\0'; + drawToSurface(x - getWidth("%s", str)/2, y, str); + *c = '\n'; + c++; + str = c; + y += height; + } + else + c++; + } + char s[strlen(str)+1]; + strcpy(s, str); + delete[] del; + + return drawToSurface(x - getWidth("%s", s)/2, y, s); +} + +SDL_Rect NFont::drawRight(int x, int y, const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return makeRect(x, y, 0, 0); + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + char* str = copyString(buffer); + char* del = str; + + for(char* c = str; *c != '\0';) + { + if(*c == '\n') + { + *c = '\0'; + drawToSurface(x - getWidth("%s", str), y, str); + *c = '\n'; + c++; + str = c; + y += height; + } + else + c++; + } + char s[strlen(str)+1]; + strcpy(s, str); + delete[] del; + + return drawToSurface(x - getWidth("%s", s), y, s); +} + +SDL_Rect NFont::drawPos(int x, int y, NFont::AnimFn posFn, const char* text, ...) const +{ + va_list lst; + va_start(lst, text); + vsprintf(buffer, text, lst); + va_end(lst); + + return drawToSurfacePos(x, y, posFn); +} + +SDL_Rect NFont::drawAll(int x, int y, NFont::AnimFn allFn, const char* text, ...) const +{ + va_list lst; + va_start(lst, text); + vsprintf(buffer, text, lst); + va_end(lst); + + allFn(x, y, data); + return data.dirtyRect; +} + + + + +// Getters +SDL_Surface* NFont::getDest() const +{ + return dest; +} + +SDL_Surface* NFont::getSurface() const +{ + return src; +} + +int NFont::getHeight(const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return height; + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + int numLines = 1; + const char* c; + + for (c = buffer; *c != '\0'; c++) + { + if(*c == '\n') + numLines++; + } + + // Actual height of letter region + line spacing + return height*numLines + lineSpacing*(numLines - 1); //height*numLines; +} + +int NFont::getWidth(const char* formatted_text, ...) const +{ + if (formatted_text == NULL) + return 0; + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + const char* c; + int charnum = 0; + int width = 0; + int bigWidth = 0; // Allows for multi-line strings + + for (c = buffer; *c != '\0'; c++) + { + charnum = (unsigned char)(*c) - 33; + + // skip spaces and nonprintable characters + if(*c == '\n') + { + bigWidth = bigWidth >= width? bigWidth : width; + width = 0; + } + else if (*c == ' ' || charnum > 222) + { + width += charWidth[0]; + continue; + } + + width += charWidth[charnum]; + } + bigWidth = bigWidth >= width? bigWidth : width; + + return bigWidth; +} + +int NFont::getAscent(const char character) const +{ + unsigned char test = (unsigned char)character; + if(test < 33 || test > 222 || (test > 126 && test < 161)) + return 0; + unsigned char num = (unsigned char)character - 33; + // Get the max ascent + int x = charPos[num]; + int i, j = 1, result = 0; + Uint32 pixel = getPixel(src, 0, src->h - 1); // bg pixel + while(j < baseline && j < src->h) + { + i = charPos[num]; + while(i < x + charWidth[num]) + { + if(getPixel(src, i, j) != pixel) + { + result = baseline - j; + j = src->h; + break; + } + i++; + } + j++; + } + return result; +} + +int NFont::getAscent(const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return ascent; + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + int max = 0; + const char* c = buffer; + + for (; *c != '\0'; c++) + { + int asc = getAscent(*c); + if(asc > max) + max = asc; + } + return max; +} + +int NFont::getDescent(const char character) const +{ + unsigned char test = (unsigned char)character; + if(test < 33 || test > 222 || (test > 126 && test < 161)) + return 0; + unsigned char num = (unsigned char)character - 33; + // Get the max descent + int x = charPos[num]; + int i, j = src->h - 1, result = 0; + Uint32 pixel = getPixel(src, 0, src->h - 1); // bg pixel + while(j > 0 && j > baseline) + { + i = charPos[num]; + while(i < x + charWidth[num]) + { + if(getPixel(src, i, j) != pixel) + { + result = j - baseline; + j = 0; + break; + } + i++; + } + j--; + } + return result; +} + +int NFont::getDescent(const char* formatted_text, ...) const +{ + if(formatted_text == NULL) + return descent; + + va_list lst; + va_start(lst, formatted_text); + vsprintf(buffer, formatted_text, lst); + va_end(lst); + + int max = 0; + const char* c = buffer; + + for (; *c != '\0'; c++) + { + int des = getDescent(*c); + if(des > max) + max = des; + } + return max; +} + +int NFont::getSpacing() const +{ + return letterSpacing; +} + +int NFont::getLineSpacing() const +{ + return lineSpacing; +} + +int NFont::getBaseline() const +{ + return baseline; +} + +int NFont::getMaxWidth() const +{ + return maxWidth; +} + + + + + +// Setters +void NFont::setSpacing(int LetterSpacing) +{ + letterSpacing = LetterSpacing; +} + +void NFont::setLineSpacing(int LineSpacing) +{ + lineSpacing = LineSpacing; +} + +void NFont::setDest(SDL_Surface* Dest) +{ + dest = Dest; +} + +int NFont::setBaseline(int Baseline) +{ + if(Baseline >= 0) + baseline = Baseline; + else + { + // Get the baseline by checking a, b, and c and averaging their lowest y-value. + // Is there a better way? + Uint32 pixel = getPixel(src, 0, src->h - 1); + int heightSum = 0; + int x, i, j; + for(unsigned char avgChar = 64; avgChar < 67; avgChar++) + { + x = charPos[avgChar]; + + j = src->h - 1; + while(j > 0) + { + i = x; + while(i - x < charWidth[64]) + { + if(getPixel(src, i, j) != pixel) + { + heightSum += j; + j = 0; + break; + } + i++; + } + j--; + } + } + baseline = int(heightSum/3.0f + 0.5f); // Round up and cast + } + return baseline; +} + + + + + + + diff --git a/source/code/Makefile b/source/code/Makefile index 73d374c..60025b7 100644 --- a/source/code/Makefile +++ b/source/code/Makefile @@ -71,4 +71,4 @@ run: $(BINARY) cd $(GAMEDIR) && ./blockattack clean: - rm *.o *.P + rm *.o *.P Libs/*.o Libs/*.P diff --git a/source/code/common.cpp b/source/code/common.cpp index eb88fda..1277d5e 100644 --- a/source/code/common.cpp +++ b/source/code/common.cpp @@ -24,6 +24,9 @@ http://blockattack.sf.net #include "common.h" #include +using namespace std; +using boost::format; + static stringstream converter; //Function to convert numbers to string diff --git a/source/code/common.h b/source/code/common.h index eb3a2dc..fc31c65 100644 --- a/source/code/common.h +++ b/source/code/common.h @@ -51,9 +51,6 @@ http://blockattack.sf.net #define _(String) gettext (String) -using namespace std; -using boost::format; - struct commonTime { unsigned int days; @@ -62,9 +59,9 @@ struct commonTime unsigned int seconds; }; -string itoa(int num) __attribute__((const)); +std::string itoa(int num) __attribute__((const)); -string getPathToSaveFiles() __attribute__((pure)); +std::string getPathToSaveFiles() __attribute__((pure)); /** @@ -72,16 +69,16 @@ string getPathToSaveFiles() __attribute__((pure)); * if the string is not an int then 0 is returned instead of throing an error * in that way this function will always return a useable value. */ -int str2int(const string &str2parse) __attribute__((const)); +int str2int(const std::string &str2parse) __attribute__((const)); -string double2str(double num) __attribute__((const)); +std::string double2str(double num) __attribute__((const)); /** * str2double parses a string and returns a double with the value of the string. * if the string is not a double then 0.0 is returned instead of throing an error * in that way this function will always return a useable value. */ -double str2double(const string &str2parse) __attribute__((const)); +double str2double(const std::string &str2parse) __attribute__((const)); #ifdef WIN32 string getMyDocumentsPath(); @@ -92,11 +89,11 @@ class TimeHandler public: static commonTime ms2ct(unsigned int milliseconds); - static commonTime getTime(const string &name); + static commonTime getTime(const std::string &name); - static commonTime peekTime(const string &name, const commonTime &toAdd); + static commonTime peekTime(const std::string &name, const commonTime &toAdd); - static commonTime addTime(const string &name, const commonTime &toAdd); + static commonTime addTime(const std::string &name, const commonTime &toAdd); }; #define MAX_VAR_LENGTH 1024 @@ -110,7 +107,7 @@ public: class Config { private: - map configMap; + std::map configMap; static Config *instance; @@ -140,36 +137,36 @@ public: *Looks in the config file and returns the string that matches the key "varName" *Returns an empty string if varName does not exist. */ - string getString(const string &varName); + std::string getString(const std::string &varName); /*getInt(varName) *Looks in the config file and returns the int that matches the key "varName" *Returns "0" if varName does not exist or cannot be parsed. */ - int getInt(const string &varName); + int getInt(const std::string &varName); /*getValue(varName) *Looks in the config file and returns the double that matches the key "varName" *Returns "0.0" if varName does not exist or cannot be parsed. */ - double getValue(const string &varName); + double getValue(const std::string &varName); /*setString(varName,content) *Sets the config variable with key "varName" to the value of "content" */ - void setString(const string &varName,const string &content); + void setString(const std::string &varName, const std::string &content); /*setInt(varName,content) *Sets the config variable with key "varName" to the value of "content" */ - void setInt(const string &varName,int content); + void setInt(const std::string &varName, int content); /** * Sets a config variable to a given (double) value * @param varName Name of the variable to set * @param content Value to give the variable */ - void setValue(const string &varName,double content); + void setValue(const std::string &varName,double content); /** * returns true if the key varName exists. This is used the first time 1.4.0 @@ -178,7 +175,7 @@ public: * @param varName Name of the variable * @return true if the varaible exists */ - bool exists(const string &varName) const; + bool exists(const std::string &varName) const; /*setDefault(varName,value) *if the variable "varName" does not exist it will be created with value "value" @@ -190,7 +187,7 @@ public: * @param varName Name of the variable * @param content The default value */ - void setDefault(const string &varName, const string &content); + void setDefault(const std::string &varName, const std::string &content); /** * Should be set if the user has requested the program to shutdown. diff --git a/source/code/main.cpp b/source/code/main.cpp index ccc7415..0f2c5a0 100644 --- a/source/code/main.cpp +++ b/source/code/main.cpp @@ -1703,7 +1703,7 @@ void OpenScoresDisplay() DrawIMG(bNext,screen,nextX,nextY); //Draw page number - string pageXofY = (format(_("Page %1% of %2%") )%(page+1)%numberOfPages).str(); + string pageXofY = (boost::format(_("Page %1% of %2%") )%(page+1)%numberOfPages).str(); NFont_Write(screen, xsize/2-nf_standard_blue_font.getWidth( pageXofY.c_str())/2,ysize-60,pageXofY.c_str()); SDL_Delay(10); @@ -2374,7 +2374,7 @@ int PuzzleLevelSelect(int Type) NFont_Write(screen, 200,200,scoreString.c_str()); NFont_Write(screen, 200,250,timeString.c_str()); - string totalString = (format("Total score: %1% in %2%:%3%")%totalScore%(totalTime/1000/60)%((totalTime/1000)%60)).str(); //"Total score: " +itoa(totalScore) + " in " + itoa(totalTime/1000/60) + " : " + itoa2((totalTime/1000)%60); + string totalString = (boost::format("Total score: %1% in %2%:%3%")%totalScore%(totalTime/1000/60)%((totalTime/1000)%60)).str(); //"Total score: " +itoa(totalScore) + " in " + itoa(totalTime/1000/60) + " : " + itoa2((totalTime/1000)%60); NFont_Write(screen, 200,600,totalString.c_str()); } diff --git a/source/code/menudef.cpp b/source/code/menudef.cpp index 2235e14..44bc997 100644 --- a/source/code/menudef.cpp +++ b/source/code/menudef.cpp @@ -191,7 +191,7 @@ static void buttonActionPortChange(Button *b) if (OpenDialogbox(200,100,port) && atoi(port)) { Config::getInstance()->setInt("portv4",atoi(port)); - format f(_("Port: %1%") ); + boost::format f(_("Port: %1%") ); f % port; b->setLabel(f.str()); } @@ -204,7 +204,7 @@ static void buttonActionIpChange(Button *b) if (OpenDialogbox(200,100,ip)) { Config::getInstance()->setString("address0",ip); - format f(_("Address: %1%") ); + boost::format f(_("Address: %1%") ); f % ip; b->setLabel(f.str()); } diff --git a/source/code/physfs_stream.hpp b/source/code/physfs_stream.hpp index d8a5b58..4e3aa92 100644 --- a/source/code/physfs_stream.hpp +++ b/source/code/physfs_stream.hpp @@ -299,7 +299,7 @@ protected: private: PHYSFS_file* _file; bool _writeStream; - vector _buf; + std::vector _buf; }; /** This class implements a C++ istream object for physfs files. diff --git a/source/code/puzzlehandler.cpp b/source/code/puzzlehandler.cpp index 03250c1..7116695 100644 --- a/source/code/puzzlehandler.cpp +++ b/source/code/puzzlehandler.cpp @@ -6,6 +6,8 @@ #include //Abstract file system. To use containers #include "physfs_stream.hpp" //To use C++ style file streams +using namespace std; + static const int maxNrOfPuzzleStages = 50; //Maximum number of puzzle stages static std::string puzzleSavePath; static std::string puzzleName; //The filename of diff --git a/source/code/stats.cpp b/source/code/stats.cpp index b2782a1..8c054a8 100644 --- a/source/code/stats.cpp +++ b/source/code/stats.cpp @@ -24,6 +24,8 @@ http://blockattack.sf.net #include "stats.h" #include "common.h" +using namespace std; + Stats* Stats::instance = NULL; Stats::Stats() diff --git a/source/code/stats.h b/source/code/stats.h index 57b1f84..ad8dacf 100644 --- a/source/code/stats.h +++ b/source/code/stats.h @@ -31,8 +31,6 @@ http://blockattack.sf.net #ifndef _STATS_H #define _STATS_H -using namespace std; - #include #include @@ -42,7 +40,7 @@ using namespace std; class Stats { private: - map statMap; + std::map statMap; static Stats *instance; @@ -58,11 +56,11 @@ public: void save(); - unsigned int getNumberOf(const string &statName); + unsigned int getNumberOf(const std::string &statName); - void addOne(const string &statName); + void addOne(const std::string &statName); - bool exists(const string &statName); + bool exists(const std::string &statName); };