diff --git a/src/Font.cpp b/src/Font.cpp index 187ada7a7..56ac47d6a 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -69,23 +69,25 @@ void Font::initLibrary() } } -Font::Font(std::string path, int size) - : fontScale(1.0f) +Font::Font(int size) : fontScale(1.0f), mSize(size) { - mPath = path; - mSize = size; - - init(); + LOG(LogInfo) << "CREATING FONT (" << mSize << ")"; } -void Font::init() +Font::~Font() +{ + LOG(LogInfo) << "~~~DESTROYING FONT (" << mSize << ")"; + deinit(); +} + +void Font::init(ResourceData data) { if(!libraryInitialized) initLibrary(); mMaxGlyphHeight = 0; - buildAtlas(); + buildAtlas(data); } void Font::deinit() @@ -94,11 +96,11 @@ void Font::deinit() glDeleteTextures(1, &textureID); } -void Font::buildAtlas() +void Font::buildAtlas(ResourceData data) { - if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face)) + if(FT_New_Memory_Face(sLibrary, data.ptr, data.length, 0, &face)) { - LOG(LogError) << "Error creating font face! (path: " << mPath.c_str(); + LOG(LogError) << "Error creating font face!"; return; } @@ -205,19 +207,13 @@ void Font::buildAtlas() fontScale *= 1.25f; mSize = (int)(mSize * (1.0f / fontScale)); deinit(); - init(); + init(data); } else { - LOG(LogInfo) << "Created font with size " << mSize << "."; + //LOG(LogInfo) << "Created font with size " << mSize << "."; } } -Font::~Font() -{ - if(textureID) - glDeleteTextures(1, &textureID); -} - void Font::drawText(std::string text, int startx, int starty, int color) { @@ -294,6 +290,144 @@ int Font::getHeight() } + + +void Font::drawCenteredText(std::string text, int xOffset, int y, unsigned int color) +{ + int w, h; + sizeText(text, &w, &h); + + int x = Renderer::getScreenWidth() - w; + x = x / 2; + x += xOffset / 2; + + drawText(text, x, y, color); +} + +//this could probably be optimized +//draws text and ensures it's never longer than xLen +void Font::drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color) +{ + int y = yStart; + + std::string line, word, temp; + int w, h; + size_t space, newline; + + while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render + { + space = text.find(' ', 0); + if(space == std::string::npos) + space = text.length() - 1; + + + word = text.substr(0, space + 1); + + //check if the next word contains a newline + newline = word.find('\n', 0); + if(newline != std::string::npos) + { + word = word.substr(0, newline); + text.erase(0, newline + 1); + }else{ + text.erase(0, space + 1); + } + + temp = line + word; + + sizeText(temp, &w, &h); + + //if we're on the last word and it'll fit on the line, just add it to the line + if((w <= xLen && text.length() == 0) || newline != std::string::npos) + { + line = temp; + word = ""; + } + + + //if the next line will be too long or we're on the last of the text, render it + if(w > xLen || text.length() == 0 || newline != std::string::npos) + { + //render line now + if(w > 0) //make sure it's not blank + drawText(line, xStart, y, color); + + //increment y by height and some extra padding for the next line + y += h + 4; + + //move the word we skipped to the next line + line = word; + }else{ + //there's still space, continue building the line + line = temp; + } + + } +} + +void Font::sizeWrappedText(std::string text, int xLen, int* xOut, int* yOut) +{ + //this is incorrect for text that is so short it doesn't need to wrap + if(xOut != NULL) + *xOut = xLen; + + int y = 0; + + std::string line, word, temp; + int w, h; + size_t space, newline; + + while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render + { + space = text.find(' ', 0); + if(space == std::string::npos) + space = text.length() - 1; + + word = text.substr(0, space + 1); + + //check if the next word contains a newline + newline = word.find('\n', 0); + if(newline != std::string::npos) + { + word = word.substr(0, newline); + text.erase(0, newline + 1); + }else{ + text.erase(0, space + 1); + } + + temp = line + word; + + sizeText(temp, &w, &h); + + //if we're on the last word and it'll fit on the line, just add it to the line + if((w <= xLen && text.length() == 0) || newline != std::string::npos) + { + line = temp; + word = ""; + } + + //if the next line will be too long or we're on the last of the text, render it + if(w > xLen || text.length() == 0 || newline != std::string::npos) + { + //increment y by height and some extra padding for the next line + y += h + 4; + + //move the word we skipped to the next line + line = word; + }else{ + //there's still space, continue building the line + line = temp; + } + + } + + if(yOut != NULL) + *yOut = y; +} + + + + //============================================================================================================= //TextCache //============================================================================================================= diff --git a/src/Font.h b/src/Font.h index ed156ed37..5da296dfc 100644 --- a/src/Font.h +++ b/src/Font.h @@ -7,17 +7,22 @@ #include #include FT_FREETYPE_H #include "Vector2.h" +#include "resources/Resource.h" class TextCache; +#define FONT_SIZE_SMALL ((unsigned int)(0.035f * Renderer::getScreenHeight())) +#define FONT_SIZE_MEDIUM ((unsigned int)(0.045f * Renderer::getScreenHeight())) +#define FONT_SIZE_LARGE ((unsigned int)(0.1f * Renderer::getScreenHeight())) + //A TrueType Font renderer that uses FreeType and OpenGL. //The library is automatically initialized when it's needed. -class Font +class Font : public Resource { public: static void initLibrary(); - Font(std::string path, int size); + Font(int size); ~Font(); FT_Face face; @@ -46,10 +51,16 @@ public: //Create a TextCache, render with it, then delete it. Best used for short text or text that changes frequently. void drawText(std::string text, int startx, int starty, int color); void sizeText(std::string text, int* w, int* h); //Sets the width and height of a given string to supplied pointers. A dimension is skipped if its pointer is NULL. + + void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color); + void sizeWrappedText(std::string text, int xLen, int* xOut, int* yOut); + void drawCenteredText(std::string text, int xOffset, int y, unsigned int color); + + int getHeight(); - void init(); - void deinit(); + void init(ResourceData data) override; + void deinit() override; int getSize(); @@ -61,14 +72,13 @@ private: static FT_Library sLibrary; static bool libraryInitialized; - void buildAtlas(); //Builds a "texture atlas," one big OpenGL texture with glyphs 32 to 128. + void buildAtlas(ResourceData data); //Builds a "texture atlas," one big OpenGL texture with glyphs 32 to 128. int textureWidth; //OpenGL texture width int textureHeight; //OpenGL texture height int mMaxGlyphHeight; float fontScale; //! 1.0 if the font would be to big for the texture - std::string mPath; int mSize; }; diff --git a/src/Renderer.h b/src/Renderer.h index 80e2ab437..fd5f9d08f 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -25,8 +25,6 @@ namespace Renderer unsigned int getScreenWidth(); unsigned int getScreenHeight(); - enum FontSize { SMALL, MEDIUM, LARGE, FONT_SIZE_COUNT }; - Font* getDefaultFont(FontSize size); void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount); //graphics commands @@ -40,10 +38,6 @@ namespace Renderer void popClipRect(); void drawRect(int x, int y, int w, int h, unsigned int color); - void drawText(std::string text, int x, int y, unsigned int color, Font* font); - void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font); - void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font); - void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut); } #endif diff --git a/src/Renderer_draw_gl.cpp b/src/Renderer_draw_gl.cpp index 05b8f4ae5..5c4f36adf 100644 --- a/src/Renderer_draw_gl.cpp +++ b/src/Renderer_draw_gl.cpp @@ -8,8 +8,6 @@ #include namespace Renderer { - bool loadedFonts = false; - std::stack clipStack; void setColor4bArray(GLubyte* array, unsigned int color) @@ -120,195 +118,4 @@ namespace Renderer { glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_COLOR_ARRAY); } - - - - Font* fonts[3] = {NULL, NULL, NULL}; - - /*void unloadFonts() - { - std::cout << "unloading fonts..."; - - for(unsigned int i = 0; i < 3; i++) - { - delete fonts[i]; - fonts[i] = NULL; - } - - loadedFonts = false; - - std::cout << "done.\n"; - }*/ - - //creates the default fonts (which shouldn't ever be deleted) - void loadFonts() - { - if(loadedFonts) - return; - - std::string fontPath = Font::getDefaultPath(); - - //make sure our font exists - if(!boost::filesystem::exists(fontPath)) - { - LOG(LogError) << "System font wasn't found! Try installing the DejaVu truetype font (pacman -S ttf-dejavu on Arch, sudo apt-get install ttf-dejavu on Debian)"; - return; - } - - float fontSizes[] = {0.035f, 0.045f, 0.1f}; - for(unsigned int i = 0; i < 3; i++) - { - fonts[i] = new Font(fontPath, (unsigned int)(fontSizes[i] * getScreenHeight())); - } - - loadedFonts = true; - - LOG(LogInfo) << "Loaded fonts successfully."; - } - - Font* getDefaultFont(FontSize size) - { - if(!loadedFonts) - loadFonts(); - - return fonts[size]; - } - - void drawText(std::string text, int x, int y, unsigned int color, Font* font) - { - font->drawText(text, x, y, color); - } - - void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font) - { - int w, h; - font->sizeText(text, &w, &h); - - int x = getScreenWidth() - w; - x = x / 2; - x += xOffset / 2; - - drawText(text, x, y, color, font); - } - - //this could probably be optimized - //draws text and ensures it's never longer than xLen - void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font) - { - int y = yStart; - - std::string line, word, temp; - int w, h; - size_t space, newline; - - while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render - { - space = text.find(' ', 0); - if(space == std::string::npos) - space = text.length() - 1; - - - word = text.substr(0, space + 1); - - //check if the next word contains a newline - newline = word.find('\n', 0); - if(newline != std::string::npos) - { - word = word.substr(0, newline); - text.erase(0, newline + 1); - }else{ - text.erase(0, space + 1); - } - - temp = line + word; - - font->sizeText(temp, &w, &h); - - //if we're on the last word and it'll fit on the line, just add it to the line - if((w <= xLen && text.length() == 0) || newline != std::string::npos) - { - line = temp; - word = ""; - } - - - //if the next line will be too long or we're on the last of the text, render it - if(w > xLen || text.length() == 0 || newline != std::string::npos) - { - //render line now - if(w > 0) //make sure it's not blank - drawText(line, xStart, y, color, font); - - //increment y by height and some extra padding for the next line - y += h + 4; - - //move the word we skipped to the next line - line = word; - }else{ - //there's still space, continue building the line - line = temp; - } - - } - } - - void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut) - { - if(xOut != NULL) - *xOut = xLen; - - int y = 0; - - std::string line, word, temp; - int w, h; - size_t space, newline; - - while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render - { - space = text.find(' ', 0); - if(space == std::string::npos) - space = text.length() - 1; - - word = text.substr(0, space + 1); - - //check if the next word contains a newline - newline = word.find('\n', 0); - if(newline != std::string::npos) - { - word = word.substr(0, newline); - text.erase(0, newline + 1); - }else{ - text.erase(0, space + 1); - } - - temp = line + word; - - font->sizeText(temp, &w, &h); - - //if we're on the last word and it'll fit on the line, just add it to the line - if((w <= xLen && text.length() == 0) || newline != std::string::npos) - { - line = temp; - word = ""; - } - - //if the next line will be too long or we're on the last of the text, render it - if(w > xLen || text.length() == 0 || newline != std::string::npos) - { - //increment y by height and some extra padding for the next line - y += h + 4; - - //move the word we skipped to the next line - line = word; - }else{ - //there's still space, continue building the line - line = temp; - } - - } - - if(yOut != NULL) - *yOut = y; - } - }; diff --git a/src/Renderer_init.cpp b/src/Renderer_init.cpp index 83afc066e..4158ba6cc 100644 --- a/src/Renderer_init.cpp +++ b/src/Renderer_init.cpp @@ -7,17 +7,9 @@ namespace Renderer { void onInit() { - for(int i = 0; i < (int)FONT_SIZE_COUNT; i++) - { - getDefaultFont((FontSize)i)->init(); - } } void onDeinit() { - for(int i = 0; i < (int)FONT_SIZE_COUNT; i++) - { - getDefaultFont((FontSize)i)->deinit(); - } } }; diff --git a/src/Window.cpp b/src/Window.cpp index ccbd9490a..1fdfc1b14 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -7,6 +7,10 @@ Window::Window() { mInputManager = new InputManager(this); + + mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_SMALL)); + mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)); + mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_LARGE)); } Window::~Window() diff --git a/src/Window.h b/src/Window.h index 9e38b03cb..399f971e8 100644 --- a/src/Window.h +++ b/src/Window.h @@ -30,6 +30,8 @@ private: InputManager* mInputManager; ResourceManager mResourceManager; std::vector mGuiStack; + + std::vector< std::shared_ptr > mDefaultFonts; }; #endif diff --git a/src/components/GuiDetectDevice.cpp b/src/components/GuiDetectDevice.cpp index 570d4c9f4..af4a61472 100644 --- a/src/components/GuiDetectDevice.cpp +++ b/src/components/GuiDetectDevice.cpp @@ -83,25 +83,25 @@ void GuiDetectDevice::update(int deltaTime) void GuiDetectDevice::render() { - Font* font = Renderer::getDefaultFont(Renderer::MEDIUM); + std::shared_ptr font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM); std::string playerString; std::stringstream stream; stream << (mCurrentPlayer + 1); stream >> playerString; - Renderer::drawCenteredText("Press a button on the device for", 0, Renderer::getScreenHeight() / 3, 0x000000FF, font); - Renderer::drawCenteredText("PLAYER " + playerString, 0, (int)(Renderer::getScreenHeight()*1.5f) / 3, 0x333333FF, font); + font->drawCenteredText("Press a button on the device for", 0, Renderer::getScreenHeight() / 3, 0x000000FF); + font->drawCenteredText("PLAYER " + playerString, 0, (int)(Renderer::getScreenHeight()*1.5f) / 3, 0x333333FF); if(mWindow->getInputManager()->getNumPlayers() > 0) { - Renderer::drawCenteredText("(P1 - hold a button to finish)", 0, (Renderer::getScreenHeight()*2) / 3, (mHoldingFinish ? 0x0000FFFF : 0x000066FF), font); + font->drawCenteredText("(P1 - hold a button to finish)", 0, (Renderer::getScreenHeight()*2) / 3, (mHoldingFinish ? 0x0000FFFF : 0x000066FF)); } if(mWindow->getInputManager()->getNumJoysticks() == 0) { - Renderer::drawCenteredText("No joysticks detected!", 0, Renderer::getScreenHeight() - (font->getHeight()*2)-10, 0xFF0000FF, font); + font->drawCenteredText("No joysticks detected!", 0, Renderer::getScreenHeight() - (font->getHeight()*2)-10, 0xFF0000FF); } - Renderer::drawCenteredText("Press F4 to quit.", 0, Renderer::getScreenHeight() - font->getHeight() - 2 , 0x000000FF, font); + font->drawCenteredText("Press F4 to quit.", 0, Renderer::getScreenHeight() - font->getHeight() - 2 , 0x000000FF); } diff --git a/src/components/GuiFastSelect.cpp b/src/components/GuiFastSelect.cpp index fee1ba337..c53893cf5 100644 --- a/src/components/GuiFastSelect.cpp +++ b/src/components/GuiFastSelect.cpp @@ -41,10 +41,11 @@ void GuiFastSelect::render() mBox->render(); - Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mTheme->getFastSelectFont()->getHeight() * 0.5f)), mTextColor, mTheme->getFastSelectFont()); - Renderer::drawCenteredText("Sort order:", 0, (int)(sh * 0.6f - (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont()); + mTheme->getFastSelectFont()->drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mTheme->getFastSelectFont()->getHeight() * 0.5f)), mTextColor); + mTheme->getDescriptionFont()->drawCenteredText("Sort order:", 0, (int)(sh * 0.6f - (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor); + std::string sortString = "<- " + mParent->getSortState().description + " ->"; - Renderer::drawCenteredText(sortString, 0, (int)(sh * 0.6f + (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont()); + mTheme->getDescriptionFont()->drawCenteredText(sortString, 0, (int)(sh * 0.6f + (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor); } bool GuiFastSelect::input(InputConfig* config, Input input) diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index c354a0478..404f5a7f9 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -26,7 +26,7 @@ bool GuiGameList::isDetailed() const GuiGameList::GuiGameList(Window* window) : GuiComponent(window), mTheme(new ThemeComponent(mWindow)), - mList(window, 0, 0, Renderer::getDefaultFont(Renderer::MEDIUM)), + mList(window, 0, 0, window->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)), mScreenshot(window), mDescription(window), mDescContainer(window), @@ -114,15 +114,17 @@ void GuiGameList::render() if(mTheme) mTheme->render(); + std::shared_ptr headerFont = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_LARGE); + //header if(!mTheme->getBool("hideHeader")) - Renderer::drawCenteredText(mSystem->getDescName(), 0, 1, 0xFF0000FF, Renderer::getDefaultFont(Renderer::LARGE)); + headerFont->drawCenteredText(mSystem->getDescName(), 0, 1, 0xFF0000FF); if(isDetailed()) { //divider if(!mTheme->getBool("hideDividers")) - Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF); + Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, headerFont->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF); mScreenshot.render(); mDescContainer.render(); @@ -324,7 +326,7 @@ void GuiGameList::updateTheme() mList.setScrollSound(mTheme->getSound("menuScroll")); mList.setFont(mTheme->getListFont()); - mList.setOffset(0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2); + mList.setOffset(0, FONT_SIZE_LARGE + 2); if(isDetailed()) { diff --git a/src/components/GuiInputConfig.cpp b/src/components/GuiInputConfig.cpp index 78f7a272a..0c84ae83b 100644 --- a/src/components/GuiInputConfig.cpp +++ b/src/components/GuiInputConfig.cpp @@ -77,25 +77,25 @@ bool GuiInputConfig::input(InputConfig* config, Input input) void GuiInputConfig::render() { - Font* font = Renderer::getDefaultFont(Renderer::MEDIUM); + std::shared_ptr font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM); std::stringstream stream; stream << "PLAYER " << mTargetConfig->getPlayerNum() + 1 << ", press..."; - Renderer::drawText(stream.str(), 10, 10, 0x000000FF, font); + font->drawText(stream.str(), 10, 10, 0x000000FF); int y = 14 + font->getHeight(); for(int i = 0; i < mCurInputId; i++) { - Renderer::drawText(inputDispName[i], 10, y, 0x00CC00FF, font); + font->drawText(inputDispName[i], 10, y, 0x00CC00FF); y += font->getHeight() + 5; } if(mCurInputId >= inputCount) { - Renderer::drawCenteredText("Basic config done!", 0, (int)(Renderer::getScreenHeight() * 0.4), 0x00CC00FF, font); - Renderer::drawCenteredText("Press any button to continue.", 0, (int)(Renderer::getScreenHeight() * 0.4) + font->getHeight() + 4, 0x000000FF, font); + font->drawCenteredText("Basic config done!", 0, (int)(Renderer::getScreenHeight() * 0.4), 0x00CC00FF); + font->drawCenteredText("Press any button to continue.", 0, (int)(Renderer::getScreenHeight() * 0.4) + font->getHeight() + 4, 0x000000FF); }else{ - Renderer::drawText(inputDispName[mCurInputId], 10, y, 0x000000FF, font); + font->drawText(inputDispName[mCurInputId], 10, y, 0x000000FF); if(mCanSkip) { int textWidth = 0; @@ -105,10 +105,10 @@ void GuiInputConfig::render() if(Renderer::getScreenWidth() / 2.5f > textWidth) textWidth = (int)(Renderer::getScreenWidth() / 2.5f); - Renderer::drawText("press Accept to skip", textWidth, y, 0x0000AAFF, font); + font->drawText("press Accept to skip", textWidth, y, 0x0000AAFF); } } if(!mErrorMsg.empty()) - Renderer::drawCenteredText(mErrorMsg, 0, Renderer::getScreenHeight() - font->getHeight() - 10, 0xFF0000FF, font); + font->drawCenteredText(mErrorMsg, 0, Renderer::getScreenHeight() - font->getHeight() - 10, 0xFF0000FF); } diff --git a/src/components/GuiMenu.cpp b/src/components/GuiMenu.cpp index 4e678d527..df18029b1 100644 --- a/src/components/GuiMenu.cpp +++ b/src/components/GuiMenu.cpp @@ -11,7 +11,8 @@ GuiMenu::GuiMenu(Window* window, GuiGameList* parent) : GuiComponent(window) { mParent = parent; - mList = new TextListComponent(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::LARGE)); + std::shared_ptr font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_LARGE); + mList = new TextListComponent(mWindow, 0, font->getHeight() + 2, font); mList->setSelectedTextColor(0x0000FFFF); populateList(); } diff --git a/src/components/SwitchComponent.cpp b/src/components/SwitchComponent.cpp index ac78c810e..ac0bc58ef 100644 --- a/src/components/SwitchComponent.cpp +++ b/src/components/SwitchComponent.cpp @@ -1,13 +1,14 @@ #include "SwitchComponent.h" #include "../Renderer.h" #include "../Font.h" +#include "../Window.h" SwitchComponent::SwitchComponent(Window* window, bool state) : GuiComponent(window), mState(state) { //mSize = Vector2u((unsigned int)(Renderer::getScreenWidth() * 0.05), // (unsigned int)(Renderer::getScreenHeight() * 0.05)); - Renderer::getDefaultFont(Renderer::MEDIUM)->sizeText("OFF", (int*)&mSize.x, (int*)&mSize.y); + mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)->sizeText("OFF", (int*)&mSize.x, (int*)&mSize.y); } bool SwitchComponent::input(InputConfig* config, Input input) @@ -25,7 +26,7 @@ void SwitchComponent::onRender() { Renderer::pushClipRect(getGlobalOffset(), getSize()); - Renderer::drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF, Renderer::getDefaultFont(Renderer::MEDIUM)); + mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF); Renderer::popClipRect(); diff --git a/src/components/TextComponent.cpp b/src/components/TextComponent.cpp index fc8dec8f3..5f6dd10a4 100644 --- a/src/components/TextComponent.cpp +++ b/src/components/TextComponent.cpp @@ -1,13 +1,14 @@ #include "TextComponent.h" #include "../Renderer.h" #include "../Log.h" +#include "../Window.h" TextComponent::TextComponent(Window* window) : GuiComponent(window), mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true) { } -TextComponent::TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size) : GuiComponent(window), +TextComponent::TextComponent(Window* window, const std::string& text, std::shared_ptr font, Vector2i pos, Vector2u size) : GuiComponent(window), mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true) { setText(text); @@ -28,7 +29,7 @@ void TextComponent::setExtent(Vector2u size) calculateExtent(); } -void TextComponent::setFont(Font* font) +void TextComponent::setFont(std::shared_ptr font) { mFont = font; @@ -47,23 +48,21 @@ void TextComponent::setText(const std::string& text) calculateExtent(); } -Font* TextComponent::getFont() const +std::shared_ptr TextComponent::getFont() const { - return (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));; + if(mFont) + return mFont; + else + return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM); } void TextComponent::onRender() { - Font* font = getFont(); - if(font == NULL) - { - LOG(LogError) << "TextComponent can't get a valid font!"; - return; - } + std::shared_ptr font = getFont(); //Renderer::pushClipRect(getGlobalOffset(), getSize()); - Renderer::drawWrappedText(mText, 0, 0, mSize.x, mColor >> 8 << 8 | getOpacity(), font); + font->drawWrappedText(mText, 0, 0, mSize.x, mColor >> 8 << 8 | getOpacity()); //Renderer::popClipRect(); @@ -72,16 +71,11 @@ void TextComponent::onRender() void TextComponent::calculateExtent() { - Font* font = getFont(); - if(font == NULL) - { - LOG(LogError) << "TextComponent can't get a valid font!"; - return; - } + std::shared_ptr font = getFont(); if(mAutoCalcExtent.x) font->sizeText(mText, (int*)&mSize.x, (int*)&mSize.y); else if(mAutoCalcExtent.y) - Renderer::sizeWrappedText(mText, getSize().x, mFont, NULL, (int*)&mSize.y); + font->sizeWrappedText(mText, getSize().x, NULL, (int*)&mSize.y); } diff --git a/src/components/TextComponent.h b/src/components/TextComponent.h index 1a1c90eb4..368d36ea1 100644 --- a/src/components/TextComponent.h +++ b/src/components/TextComponent.h @@ -8,9 +8,9 @@ class TextComponent : public GuiComponent { public: TextComponent(Window* window); - TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size); + TextComponent(Window* window, const std::string& text, std::shared_ptr font, Vector2i pos, Vector2u size); - void setFont(Font* font); + void setFont(std::shared_ptr font); void setBox(Vector2i pos, Vector2u size); void setExtent(Vector2u size); //Use Vector2u(0, 0) to automatically generate extent on a single line. Use Vector2(value, 0) to automatically generate extent for wrapped text. void setText(const std::string& text); @@ -19,12 +19,12 @@ public: void onRender() override; private: - Font* getFont() const; + std::shared_ptr getFont() const; void calculateExtent(); unsigned int mColor; - Font* mFont; + std::shared_ptr mFont; Vector2 mAutoCalcExtent; std::string mText; }; diff --git a/src/components/TextListComponent.h b/src/components/TextListComponent.h index e5c16e2fd..378e3b617 100644 --- a/src/components/TextListComponent.h +++ b/src/components/TextListComponent.h @@ -19,7 +19,7 @@ template class TextListComponent : public GuiComponent { public: - TextListComponent(Window* window, int offsetX, int offsetY, Font* font); + TextListComponent(Window* window, int offsetX, int offsetY, std::shared_ptr font); virtual ~TextListComponent(); bool input(InputConfig* config, Input input); @@ -44,7 +44,7 @@ public: T getObject(int i); void setSelection(int i); - void setFont(Font* f); + void setFont(std::shared_ptr f); protected: void onRender(); @@ -62,7 +62,7 @@ private: int mMarqueeOffset; int mMarqueeTime; - Font* mFont; + std::shared_ptr mFont; unsigned int mSelectorColor, mSelectedTextColorOverride; bool mDrawCentered; @@ -81,7 +81,7 @@ private: }; template -TextListComponent::TextListComponent(Window* window, int offsetX, int offsetY, Font* font) : GuiComponent(window) +TextListComponent::TextListComponent(Window* window, int offsetX, int offsetY, std::shared_ptr font) : GuiComponent(window) { mSelection = 0; mScrollDir = 0; @@ -132,7 +132,7 @@ void TextListComponent::onRender() if(mRowVector.size() == 0) { - Renderer::drawCenteredText("The list is empty.", 0, y, 0xFF0000FF, mFont); + mFont->drawCenteredText("The list is empty.", 0, y, 0xFF0000FF); return; } @@ -156,9 +156,9 @@ void TextListComponent::onRender() unsigned int color = (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color; if(mDrawCentered) - Renderer::drawCenteredText(row.name, x, y, color, mFont); + mFont->drawCenteredText(row.name, x, y, color); else - Renderer::drawText(row.name, x, y, color, mFont); + mFont->drawText(row.name, x, y, color); y += entrySize; } @@ -202,7 +202,6 @@ bool TextListComponent::input(InputConfig* config, Input input) return true; } }else{ - //if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::PAGEDOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0) || (button == InputManager::PAGEUP && mScrollDir < 0)) if(config->isMappedTo("down", input) || config->isMappedTo("up", input) || config->isMappedTo("pagedown", input) || config->isMappedTo("pageup", input)) { stopScrolling(); @@ -397,7 +396,7 @@ void TextListComponent::setScrollSound(std::shared_ptr & sound) } template -void TextListComponent::setFont(Font* font) +void TextListComponent::setFont(std::shared_ptr font) { mFont = font; } diff --git a/src/components/ThemeComponent.cpp b/src/components/ThemeComponent.cpp index 0e54caa81..0a9453dee 100644 --- a/src/components/ThemeComponent.cpp +++ b/src/components/ThemeComponent.cpp @@ -35,28 +35,28 @@ std::string ThemeComponent::getString(std::string name) GuiBoxData ThemeComponent::getBoxData() { return mBoxData; } -Font* ThemeComponent::getListFont() +std::shared_ptr ThemeComponent::getListFont() { - if(mListFont == NULL) - return Renderer::getDefaultFont(Renderer::MEDIUM); - else + if(mListFont) return mListFont; -} - -Font* ThemeComponent::getDescriptionFont() -{ - if(mDescFont == NULL) - return Renderer::getDefaultFont(Renderer::SMALL); else - return mDescFont; + return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM); } -Font* ThemeComponent::getFastSelectFont() +std::shared_ptr ThemeComponent::getDescriptionFont() +{ + if(mDescFont) + return mDescFont; + else + return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_SMALL); +} + +std::shared_ptr ThemeComponent::getFastSelectFont() { if(mFastSelectFont == NULL) - return Renderer::getDefaultFont(Renderer::LARGE); - else return mFastSelectFont; + else + return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_LARGE); } ThemeComponent::ThemeComponent(Window* window) : GuiComponent(window) @@ -72,9 +72,9 @@ ThemeComponent::ThemeComponent(Window* window) : GuiComponent(window) AudioManager::getInstance()->registerSound(mSoundMap["menuBack"]); AudioManager::getInstance()->registerSound(mSoundMap["menuOpen"]); - mListFont = NULL; - mDescFont = NULL; - mFastSelectFont = NULL; + mListFont.reset(); + mDescFont.reset(); + mFastSelectFont.reset(); setDefaults(); } @@ -102,7 +102,7 @@ void ThemeComponent::setDefaults() mFloatMap["gameImageOriginX"] = 0.5; mFloatMap["gameImageOriginY"] = 0; mFloatMap["gameImageOffsetX"] = mFloatMap["listOffsetX"] / 2; - mFloatMap["gameImageOffsetY"] = (float)Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / (float)Renderer::getScreenHeight(); + mFloatMap["gameImageOffsetY"] = (float)FONT_SIZE_LARGE / (float)Renderer::getScreenHeight(); mFloatMap["gameImageWidth"] = mFloatMap["listOffsetX"]; mFloatMap["gameImageHeight"] = 0; @@ -121,22 +121,9 @@ void ThemeComponent::setDefaults() mBoxData.verticalTiled = false; mBoxData.cornerPath = ""; - if(mListFont != NULL) - { - delete mListFont; - mListFont = NULL; - } - - if(mDescFont != NULL) - { - delete mDescFont; - mDescFont = NULL; - } - if(mFastSelectFont != NULL) - { - delete mFastSelectFont; - mFastSelectFont = NULL; - } + mListFont.reset(); + mDescFont.reset(); + mFastSelectFont.reset(); } void ThemeComponent::deleteComponents() @@ -148,12 +135,10 @@ void ThemeComponent::deleteComponents() clearChildren(); - //deletes fonts if any were created setDefaults(); } - void ThemeComponent::readXML(std::string path, bool detailed) { if(mPath == path) @@ -248,9 +233,9 @@ void ThemeComponent::readXML(std::string path, bool detailed) mSoundMap["menuOpen"]->loadFile(expandPath(root.child("menuOpenSound").text().get())); //fonts - mListFont = resolveFont(root.child("listFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::MEDIUM)->getSize()); - mDescFont = resolveFont(root.child("descriptionFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::SMALL)->getSize()); - mFastSelectFont = resolveFont(root.child("fastSelectFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::LARGE)->getSize()); + mListFont = resolveFont(root.child("listFont"), Font::getDefaultPath(), FONT_SIZE_MEDIUM); + mDescFont = resolveFont(root.child("descriptionFont"), Font::getDefaultPath(), FONT_SIZE_SMALL); + mFastSelectFont = resolveFont(root.child("fastSelectFont"), Font::getDefaultPath(), FONT_SIZE_LARGE); //actually read the components createComponentChildren(root, this); @@ -348,7 +333,7 @@ float ThemeComponent::resolveExp(std::string str, float defaultVal) exp.setExpression(str); //set variables - exp.setVariable("headerHeight", (float)(Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / Renderer::getScreenHeight())); + exp.setVariable("headerHeight", (float)(FONT_SIZE_LARGE / Renderer::getScreenHeight())); exp.setVariable("infoWidth", mFloatMap["listOffsetX"]); return exp.eval(); @@ -407,7 +392,7 @@ float ThemeComponent::strToFloat(std::string str, float defaultVal) return ret; } -Font* ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize) +std::shared_ptr ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize) { if(!node) return NULL; @@ -425,25 +410,5 @@ Font* ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, size = defaultSize; } - return new Font(path, size); -} - -void ThemeComponent::init() -{ - //fonts are special - if(mListFont) mListFont->init(); - if(mDescFont) mDescFont->init(); - if(mFastSelectFont) mFastSelectFont->init(); - - GuiComponent::init(); -} - -void ThemeComponent::deinit() -{ - GuiComponent::deinit(); - - //fonts are special - if(mListFont) mListFont->deinit(); - if(mDescFont) mDescFont->deinit(); - if(mFastSelectFont) mFastSelectFont->deinit(); + return mWindow->getResourceManager()->getFont(path, size); } diff --git a/src/components/ThemeComponent.h b/src/components/ThemeComponent.h index c6ec05f4e..e5e9c8ab6 100644 --- a/src/components/ThemeComponent.h +++ b/src/components/ThemeComponent.h @@ -20,18 +20,15 @@ public: GuiBoxData getBoxData(); - void init(); - void deinit(); - unsigned int getColor(std::string name); bool getBool(std::string name); float getFloat(std::string name); std::shared_ptr & getSound(std::string name); std::string getString(std::string name); - Font* getListFont(); - Font* getDescriptionFont(); - Font* getFastSelectFont(); + std::shared_ptr getListFont(); + std::shared_ptr getDescriptionFont(); + std::shared_ptr getFastSelectFont(); private: void setDefaults(); @@ -45,7 +42,7 @@ private: unsigned int resolveColor(std::string str, unsigned int defaultColor = 0x000000FF); void splitString(std::string str, char delim, std::string* before, std::string* after); float strToFloat(std::string str, float defaultVal = 0.0f); - Font* resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize); + std::shared_ptr resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize); std::string mPath; @@ -56,10 +53,10 @@ private: std::map mStringMap; GuiBoxData mBoxData; - - Font* mListFont; - Font* mDescFont; - Font* mFastSelectFont; + + std::shared_ptr mListFont; + std::shared_ptr mDescFont; + std::shared_ptr mFastSelectFont; }; #endif diff --git a/src/main.cpp b/src/main.cpp index 4823308bb..e5cacd5fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #endif + #include namespace fs = boost::filesystem; @@ -210,7 +211,7 @@ int main(int argc, char* argv[]) nrOfFrames = 0; timeElapsed = 0; } - Renderer::drawText(fpsString, 50, 50, 0x00FF00FF, Renderer::getDefaultFont(Renderer::MEDIUM)); + window.getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(fpsString, 50, 50, 0x00FF00FF); } //sleep if we're past our threshold diff --git a/src/resources/ResourceManager.cpp b/src/resources/ResourceManager.cpp index eed1666bc..7b0b7d768 100644 --- a/src/resources/ResourceManager.cpp +++ b/src/resources/ResourceManager.cpp @@ -40,14 +40,37 @@ std::shared_ptr ResourceManager::getTexture(const std::string& return mTextureMap[path].lock(); } +std::shared_ptr ResourceManager::getFont(const std::string& path, int size) +{ + if(path.empty() || size == 0) + return std::shared_ptr(); //NULL pointer + + std::pair fontDef(path, size); + if(mFontMap[fontDef].expired()) + { + std::shared_ptr ret(new Font(size)); + mFontMap[fontDef] = std::weak_ptr(ret); + + initializeResource(path, ret); + + return ret; + } + + return mFontMap[fontDef].lock(); +} + void ResourceManager::init() { for(auto iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++) { if(!iter->second.expired()) - { initializeResource(iter->first, iter->second.lock()); - } + } + + for(auto iter = mFontMap.begin(); iter != mFontMap.end(); iter++) + { + if(!iter->second.expired()) + initializeResource(iter->first.first, iter->second.lock()); } } @@ -58,6 +81,12 @@ void ResourceManager::deinit() if(!iter->second.expired()) iter->second.lock()->deinit(); } + + for(auto iter = mFontMap.begin(); iter != mFontMap.end(); iter++) + { + if(!iter->second.expired()) + iter->second.lock()->deinit(); + } } void ResourceManager::initializeResource(const std::string& path, std::shared_ptr resource) diff --git a/src/resources/ResourceManager.h b/src/resources/ResourceManager.h index 435aa221b..eecb73ddb 100644 --- a/src/resources/ResourceManager.h +++ b/src/resources/ResourceManager.h @@ -5,7 +5,7 @@ #include #include "Resource.h" #include "TextureResource.h" - +#include "../Font.h" //The ResourceManager exists to: //1. Automatically deal with initializing/deinitializing various resources (OpenGL textures, SDL audio) @@ -22,6 +22,7 @@ class ResourceManager { public: std::shared_ptr getTexture(const std::string& path); + std::shared_ptr getFont(const std::string& path, int size); void init(); void deinit(); @@ -31,4 +32,6 @@ private: ResourceData loadFile(const std::string& path); std::map< std::string, std::weak_ptr > mTextureMap; + + std::map< std::pair, std::weak_ptr > mFontMap; };