diff --git a/src/Font.cpp b/src/Font.cpp index 8ca30b1e9..5ed2372a3 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -5,31 +5,57 @@ #include "Renderer.h" FT_Library Font::sLibrary; +bool Font::libraryInitialized = false; -int Font::getDpiX() { return 300; } -int Font::getDpiY() { return 300; } +int Font::getDpiX() { return 96; } +int Font::getDpiY() { return 96; } void Font::initLibrary() { if(FT_Init_FreeType(&sLibrary)) { std::cerr << "Error initializing FreeType!\n"; + }else{ + libraryInitialized = true; } } Font::Font(std::string path, int size) { + //register to receive init/deinit callbacks + Renderer::registerComponent(this); + + mPath = path; + mSize = size; + + onInit(); +} + +void Font::onInit() +{ + if(!libraryInitialized) + initLibrary(); + mMaxGlyphHeight = 0; - if(FT_New_Face(sLibrary, path.c_str(), 0, &face)) + if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face)) { - std::cerr << "Error creating font face! (path: " << path.c_str() << "\n"; - while(true); + std::cerr << "Error creating font face! (path: " << mPath.c_str() << "\n"; + return; } - FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY()); + //FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY()); + FT_Set_Pixel_Sizes(face, 0, mSize); buildAtlas(); + + FT_Done_Face(face); +} + +void Font::onDeinit() +{ + if(textureID) + glDeleteTextures(1, &textureID); } void Font::buildAtlas() @@ -130,9 +156,10 @@ void Font::buildAtlas() Font::~Font() { - FT_Done_Face(face); + Renderer::unregisterComponent(this); - glDeleteTextures(1, &textureID); + if(textureID) + glDeleteTextures(1, &textureID); } @@ -167,6 +194,13 @@ struct tex { void Font::drawText(std::string text, int startx, int starty, int color) { + if(!textureID) + { + std::cerr << "Error - tried to draw with Font that has no texture loaded!\n"; + return; + } + + starty += mMaxGlyphHeight; //padding (another 0.5% is added to the bottom through the sizeText function) @@ -255,7 +289,7 @@ void Font::sizeText(std::string text, int* w, int* h) { unsigned char letter = text[i]; if(letter < 32 || letter >= 128) - continue; + letter = 127; cwidth += charData[letter].advX; } @@ -267,3 +301,8 @@ void Font::sizeText(std::string text, int* w, int* h) if(h != NULL) *h = mMaxGlyphHeight + mMaxGlyphHeight * 0.5; } + +int Font::getHeight() +{ + return mMaxGlyphHeight * 1.5; +} diff --git a/src/Font.h b/src/Font.h index 4311006c6..2d08f0ea7 100644 --- a/src/Font.h +++ b/src/Font.h @@ -2,13 +2,14 @@ #define _FONT_H_ #include +#include "GuiComponent.h" #include "platform.h" #include GLHEADER #include #include FT_FREETYPE_H //A TrueType Font renderer that uses FreeType and OpenGL. initLibrary() MUST be called before using it. -class Font +class Font : GuiComponent { public: static void initLibrary(); @@ -37,17 +38,26 @@ public: void drawText(std::string text, int startx, int starty, int color); //Render some text using this font. void sizeText(std::string text, int* w, int* h); //Sets the width and height of a given string to given pointers. Skipped if pointer is NULL. + int getHeight(); + + void onInit(); + void onDeinit(); private: static int getDpiX(); static int getDpiY(); + static FT_Library sLibrary; + static bool libraryInitialized; void buildAtlas(); //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; + + std::string mPath; + int mSize; }; #endif diff --git a/src/Renderer.h b/src/Renderer.h index 1b748d2bc..8250bba7a 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -3,9 +3,12 @@ #include #include -#include "Font.h" +#include "platform.h" +#include GLHEADER +//#include "Font.h" class GuiComponent; +class Font; //The Renderer provides several higher-level functions for drawing (rectangles, text, etc.). //Defined in multiple files - Renderer.cpp has the GuiComponent stuff, Renderer_draw_* includes renderer-specific drawing implementations, and Renderer_init_* includes renderer-specific init/deinit. @@ -26,15 +29,15 @@ namespace Renderer unsigned int getScreenHeight(); enum FontSize { SMALL, MEDIUM, LARGE }; - int getFontHeight(FontSize size); //sometimes font size is needed before fonts have been loaded; this takes care of that + Font* getDefaultFont(FontSize size); void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount); //drawing commands void swapBuffers(); 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, FontSize fontsize = MEDIUM); - void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, FontSize fontsize = MEDIUM); - void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, FontSize fontsize = MEDIUM); + 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); } #endif diff --git a/src/Renderer_draw_gl.cpp b/src/Renderer_draw_gl.cpp index 3291747ac..c19963e7f 100644 --- a/src/Renderer_draw_gl.cpp +++ b/src/Renderer_draw_gl.cpp @@ -57,10 +57,29 @@ namespace Renderer { - Font* fonts[3] = {NULL, NULL, NULL}; + + //this is never really used, but is here "just in case" + 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"; + } + void loadFonts() { + if(loadedFonts) + unloadFonts(); + std::cout << "loading fonts..."; std::string fontPath = "LinLibertine_R.ttf"; @@ -77,10 +96,10 @@ namespace Renderer { } } - float fontSizes[] = {0.004, 0.006, 0.009}; + float fontSizes[] = {0.035, 0.05, 0.1}; for(unsigned int i = 0; i < 3; i++) { - fonts[i] = new Font(fontPath, (unsigned int)(fontSizes[i] * getScreenWidth())); + fonts[i] = new Font(fontPath, (unsigned int)(fontSizes[i] * getScreenHeight())); } loadedFonts = true; @@ -88,22 +107,7 @@ namespace Renderer { std::cout << "done\n"; } - 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"; - } - - Font* getFont(FontSize size) + Font* getDefaultFont(FontSize size) { if(!loadedFonts) loadFonts(); @@ -111,36 +115,13 @@ namespace Renderer { return fonts[size]; } - - int getFontHeight(FontSize size) + void drawText(std::string text, int x, int y, unsigned int color, Font* font) { - if(!loadedFonts) - loadFonts(); - - int h; - getFont(size)->sizeText("HEIGHT", NULL, &h); - - return h; + font->drawText(text, x, y, color); } - void drawText(std::string text, int x, int y, unsigned int color, FontSize font) + void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font) { - if(!loadedFonts) - loadFonts(); - - //if(x < 0) - // std::cout << "drawing at " << x << std::endl; - - getFont(font)->drawText(text, x, y, color); - } - - void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, FontSize fontsize) - { - if(!loadedFonts) - loadFonts(); - - Font* font = getFont(fontsize); - int w, h; font->sizeText(text, &w, &h); @@ -149,18 +130,13 @@ namespace Renderer { x += xOffset * 0.5; - drawText(text, x, y, color, fontsize); + 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, FontSize fontsize) + void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font) { - if(!loadedFonts) - loadFonts(); - - Font* font = getFont(fontsize); - int y = yStart; std::string line, word, temp; @@ -203,7 +179,7 @@ namespace Renderer { { //render line now if(w > 0) //make sure it's not blank - drawText(line, xStart, y, color, fontsize); + drawText(line, xStart, y, color, font); //increment y by height and some extra padding for the next line y += h + 4; diff --git a/src/Renderer_init_rpi.cpp b/src/Renderer_init_rpi.cpp index 94942b907..a4c66539d 100644 --- a/src/Renderer_init_rpi.cpp +++ b/src/Renderer_init_rpi.cpp @@ -215,7 +215,7 @@ namespace Renderer { onDeinit(); - unloadFonts(); + //unloadFonts(); destroySurface(); } }; diff --git a/src/Renderer_init_sdlgl.cpp b/src/Renderer_init_sdlgl.cpp index 2253ca7a5..13d3d4b97 100644 --- a/src/Renderer_init_sdlgl.cpp +++ b/src/Renderer_init_sdlgl.cpp @@ -79,7 +79,7 @@ namespace Renderer if(!createdSurface) return false; - Font::initLibrary(); + //Font::initLibrary(); glViewport(0, 0, display_width, display_height); glOrtho(0, display_width, display_height, 0, -1.0, 1.0); @@ -95,7 +95,7 @@ namespace Renderer { onDeinit(); - unloadFonts(); + //unloadFonts(); destroySurface(); } }; diff --git a/src/components/GuiFastSelect.cpp b/src/components/GuiFastSelect.cpp index 96a594599..4823fed07 100644 --- a/src/components/GuiFastSelect.cpp +++ b/src/components/GuiFastSelect.cpp @@ -51,7 +51,7 @@ void GuiFastSelect::onRender() mBox->render(); - Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, sh * 0.5 - (Renderer::getFontHeight(Renderer::LARGE) * 0.5), mTextColor, Renderer::LARGE); + Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, sh * 0.5 - (Renderer::getDefaultFont(Renderer::LARGE)->getHeight() * 0.5), mTextColor, Renderer::getDefaultFont(Renderer::LARGE)); } void GuiFastSelect::onInput(InputManager::InputButton button, bool keyDown) diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index 1d0218c2f..c011e80cd 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -21,7 +21,7 @@ GuiGameList::GuiGameList(bool useDetail) //Those with smaller displays may prefer the older view. if(mDetailed) { - mList = new GuiList(Renderer::getScreenWidth() * sInfoWidth, Renderer::getFontHeight(Renderer::LARGE) + 2); + mList = new GuiList(Renderer::getScreenWidth() * sInfoWidth, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2); mScreenshot = new GuiImage(Renderer::getScreenWidth() * sInfoWidth * 0.5, Renderer::getScreenHeight() * mTheme->getGameImageOffsetY(), "", Renderer::getScreenWidth() * sInfoWidth * 0.7, 0, false); mScreenshot->setOrigin(mTheme->getGameImageOriginX(), mTheme->getGameImageOriginY()); @@ -31,7 +31,7 @@ GuiGameList::GuiGameList(bool useDetail) mImageAnimation->addChild(mScreenshot); addChild(mImageAnimation); }else{ - mList = new GuiList(0, Renderer::getFontHeight(Renderer::LARGE) + 2); + mList = new GuiList(0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2); mScreenshot = NULL; mImageAnimation = NULL; } @@ -93,13 +93,13 @@ void GuiGameList::onRender() //header if(!mTheme->getHeaderHidden()) - Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0xFF0000FF, Renderer::LARGE); + Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0xFF0000FF, Renderer::getDefaultFont(Renderer::LARGE)); if(mDetailed) { //divider if(!mTheme->getDividersHidden()) - Renderer::drawRect(Renderer::getScreenWidth() * mTheme->getListOffsetX() - 4, Renderer::getFontHeight(Renderer::LARGE) + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF); + Renderer::drawRect(Renderer::getScreenWidth() * mTheme->getListOffsetX() - 4, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF); //if we're not scrolling and we have selected a non-folder if(!mList->isScrolling() && mList->getSelectedObject() && !mList->getSelectedObject()->isFolder()) @@ -108,7 +108,7 @@ void GuiGameList::onRender() std::string desc = game->getDescription(); if(!desc.empty()) - Renderer::drawWrappedText(desc, Renderer::getScreenWidth() * 0.03, mScreenshot->getOffsetY() + mScreenshot->getHeight() + 12, Renderer::getScreenWidth() * (mTheme->getListOffsetX() - 0.03), mTheme->getDescColor(), Renderer::SMALL); + Renderer::drawWrappedText(desc, Renderer::getScreenWidth() * 0.03, mScreenshot->getOffsetY() + mScreenshot->getHeight() + 12, Renderer::getScreenWidth() * (mTheme->getListOffsetX() - 0.03), mTheme->getDescColor(), Renderer::getDefaultFont(Renderer::SMALL)); } } } diff --git a/src/components/GuiInputConfig.cpp b/src/components/GuiInputConfig.cpp index eb2294e26..a9d99585c 100644 --- a/src/components/GuiInputConfig.cpp +++ b/src/components/GuiInputConfig.cpp @@ -38,19 +38,22 @@ void GuiInputConfig::onRender() { Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFFFF); - int height = Renderer::getFontHeight(Renderer::MEDIUM) + 6; + Font* font = Renderer::getDefaultFont(Renderer::MEDIUM); - Renderer::drawCenteredText("It looks like you have a joystick plugged in!", 0, 2, 0x000000FF); - Renderer::drawCenteredText("POV hats (some D-Pads) are automatically mapped to directions.", 0, height, 0x000000FF); - Renderer::drawCenteredText("You can press a keyboard key to skip any input.", 0, height * 2, 0x000000FF); - Renderer::drawCenteredText("If you want to remap later, just delete ~/.es_input.cfg.", 0, height * 3, 0x000000FF); - Renderer::drawCenteredText("This interface only configures the first joystick plugged in.", 0, height * 4, 0x000000FF); - Renderer::drawCenteredText("Remember - you'll need to set up your emulator separately!", 0, Renderer::getScreenHeight() - height, 0x000000FF); + int height = font->getHeight() + 6; + + + Renderer::drawCenteredText("It looks like you have a joystick plugged in!", 0, 2, 0x000000FF, font); + Renderer::drawCenteredText("POV hats (some D-Pads) are automatically mapped to directions.", 0, height, 0x000000FF, font); + Renderer::drawCenteredText("You can press a keyboard key to skip any input.", 0, height * 2, 0x000000FF, font); + Renderer::drawCenteredText("If you want to remap later, just delete ~/.es_input.cfg.", 0, height * 3, 0x000000FF, font); + Renderer::drawCenteredText("This interface only configures the first joystick plugged in.", 0, height * 4, 0x000000FF, font); + Renderer::drawCenteredText("Remember - you'll need to set up your emulator separately!", 0, Renderer::getScreenHeight() - height, 0x000000FF, font); if(mDone) - Renderer::drawCenteredText("All done! Press a keyboard key to save.", 0, height * 5, 0x00BB00FF); + Renderer::drawCenteredText("All done! Press a keyboard key to save.", 0, height * 5, 0x00BB00FF, font); else - Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 0, height * 5, 0x00C000FF); + Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 0, height * 5, 0x00C000FF, font); } void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown) diff --git a/src/components/GuiList.cpp b/src/components/GuiList.cpp index c5e43cc6e..35747aee6 100644 --- a/src/components/GuiList.cpp +++ b/src/components/GuiList.cpp @@ -16,7 +16,7 @@ GuiList::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize mTextOffsetX = 0; - mFont = fontsize; + mFont = Renderer::getDefaultFont(fontsize); mSelectorColor = 0x000000FF; mSelectedTextColorOverride = 0x0000FF; mScrollSound = NULL; @@ -35,7 +35,7 @@ template void GuiList::onRender() { const int cutoff = getOffsetY(); - const int entrySize = Renderer::getFontHeight(mFont) + 5; + const int entrySize = mFont->getHeight() + 5; int startEntry = 0; @@ -69,7 +69,7 @@ void GuiList::onRender() //draw selector bar if(mSelection == i) { - Renderer::drawRect(getOffsetX(), y, Renderer::getScreenWidth(), Renderer::getFontHeight(mFont), mSelectorColor); + Renderer::drawRect(getOffsetX(), y, Renderer::getScreenWidth(), mFont->getHeight(), mSelectorColor); } ListRow row = mRowVector.at((unsigned int)i); diff --git a/src/components/GuiList.h b/src/components/GuiList.h index 22ae972a4..0b5e14155 100644 --- a/src/components/GuiList.h +++ b/src/components/GuiList.h @@ -2,6 +2,7 @@ #define _GUILIST_H_ #include "../Renderer.h" +#include "../Font.h" #include "../GuiComponent.h" #include "../InputManager.h" #include @@ -52,7 +53,7 @@ private: int mScrollDir, mScrollAccumulator; bool mScrolling; - Renderer::FontSize mFont; + Font* mFont; unsigned int mSelectorColor, mSelectedTextColorOverride; bool mDrawCentered; diff --git a/src/components/GuiMenu.cpp b/src/components/GuiMenu.cpp index 72a28ac53..c96984728 100644 --- a/src/components/GuiMenu.cpp +++ b/src/components/GuiMenu.cpp @@ -6,7 +6,7 @@ GuiMenu::GuiMenu(GuiComponent* parent) mParent = parent; parent->pause(); - mList = new GuiList(0, Renderer::getFontHeight(Renderer::LARGE) + 2, Renderer::LARGE); + mList = new GuiList(0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::LARGE); populateList(); addChild(mList); diff --git a/src/components/GuiTheme.cpp b/src/components/GuiTheme.cpp index 3c1b5fc40..f51709c5d 100644 --- a/src/components/GuiTheme.cpp +++ b/src/components/GuiTheme.cpp @@ -65,7 +65,7 @@ void GuiTheme::setDefaults() mGameImageOriginX = 0.5; mGameImageOriginY = 0; mGameImageOffsetX = mListOffsetX / 2; - mGameImageOffsetY = (float)Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight(); + mGameImageOffsetY = (float)Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / Renderer::getScreenHeight(); mGameImageWidth = mListOffsetX; mGameImageHeight = 0; @@ -264,7 +264,7 @@ float GuiTheme::resolveExp(std::string str, float defaultVal) exp.setExpression(str); //set variables - exp.setVariable("headerHeight", Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight()); + exp.setVariable("headerHeight", Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / Renderer::getScreenHeight()); exp.setVariable("infoWidth", mListOffsetX); return exp.eval(); diff --git a/src/main.cpp b/src/main.cpp index 23ad3b762..9639b4aeb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,7 +166,7 @@ int main(int argc, char* argv[]) ss << framerate; std::string fps; ss >> fps; - Renderer::drawText(fps, 50, 50, 0x00FF00); + Renderer::drawText(fps, 50, 50, 0x00FF00, Renderer::getDefaultFont(Renderer::MEDIUM)); }