diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 69d39c7..2f0354a 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -447,6 +447,15 @@ AppFrame::AppFrame() : menuBar->Append(menu, wxT("Audio &Sample Rate")); + displayMenu = new wxMenu; + + menuBar->Append(displayMenu, wxT("&Display")); + wxMenuItem *itmNormal = displayMenu->AppendRadioItem(wxID_DISPLAY_BASE, "Normal font (1x)"); + displayMenu->AppendRadioItem(wxID_DISPLAY_BASE + 1, "Medium font (1.3x)"); + displayMenu->AppendRadioItem(wxID_DISPLAY_BASE + 2, "Large font (2x)"); + + itmNormal->Check(true); + #ifdef USE_HAMLIB rigModel = wxGetApp().getConfig()->getRigModel(); @@ -911,6 +920,16 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } else if (event.GetId() == wxID_THEME_RADAR) { ThemeMgr::mgr.setTheme(COLOR_THEME_RADAR); } + //Display : font sizes + else if (event.GetId() == wxID_DISPLAY_BASE) { + GLFont::setScale(GLFont::GLFONT_SCALE_NORMAL); + } + else if (event.GetId() == wxID_DISPLAY_BASE + 1) { + GLFont::setScale(GLFont::GLFONT_SCALE_MEDIUM); + } + else if (event.GetId() == wxID_DISPLAY_BASE + 2) { + GLFont::setScale(GLFont::GLFONT_SCALE_LARGE); + } if (event.GetId() >= wxID_SETTINGS_BASE && event.GetId() < settingsIdMax) { int setIdx = event.GetId()-wxID_SETTINGS_BASE; diff --git a/src/AppFrame.h b/src/AppFrame.h index 8679c9a..2ecce1a 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -47,6 +47,8 @@ #define wxID_BANDWIDTH_BASE 2150 #define wxID_BANDWIDTH_MANUAL 2200 +#define wxID_DISPLAY_BASE 2250 + #define wxID_SETTINGS_BASE 2300 #define wxID_DEVICE_ID 3500 @@ -140,6 +142,7 @@ private: std::map directSamplingMenuItems; wxMenuBar *menuBar; wxMenu *sampleRateMenu; + wxMenu *displayMenu; wxMenuItem *agcMenuItem; wxMenuItem *iqSwapMenuItem; wxMenuItem *lowPerfMenuItem; diff --git a/src/util/GLFont.cpp b/src/util/GLFont.cpp index 3c6ae1c..636c266 100644 --- a/src/util/GLFont.cpp +++ b/src/util/GLFont.cpp @@ -21,7 +21,43 @@ GLFontStringCache::GLFontStringCache() { gc = 0; } -GLFont GLFont::fonts[GLFONT_MAX]; +//Static initialization of all available fonts, +//using aggregate syntax (Cx11+) +GLFont GLFont::fonts[GLFont::GLFontSize::GLFONT_SIZE_MAX] = { + + { GLFont::GLFontSize::GLFONT_SIZE12, L"vera_sans_mono12.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE16, L"vera_sans_mono16.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE18, L"vera_sans_mono18.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE22, L"vera_sans_mono22.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE24, L"vera_sans_mono24.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE32, L"vera_sans_mono32.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE36, L"vera_sans_mono36.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE42, L"vera_sans_mono42.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE48, L"vera_sans_mono48.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE64, L"vera_sans_mono64.fnt" }, + { GLFont::GLFontSize::GLFONT_SIZE96, L"vera_sans_mono96.fnt" }, + +}; + +//default mapping: one-to-one (normal scale factor) +GLFont::GLFontSize GLFont::userFontZoomMapping[GLFont::GLFontSize::GLFONT_SIZE_MAX] = { + GLFont::GLFontSize::GLFONT_SIZE12, + GLFont::GLFontSize::GLFONT_SIZE16, + GLFont::GLFontSize::GLFONT_SIZE18, + GLFont::GLFontSize::GLFONT_SIZE22, + GLFont::GLFontSize::GLFONT_SIZE24, + GLFont::GLFontSize::GLFONT_SIZE32, + GLFont::GLFontSize::GLFONT_SIZE36, + GLFont::GLFontSize::GLFONT_SIZE42, + GLFont::GLFontSize::GLFONT_SIZE48, + GLFont::GLFontSize::GLFONT_SIZE64, + GLFont::GLFontSize::GLFONT_SIZE96 +}; + +GLFont::GLFontScale GLFont::currentScaleFactor = GLFont::GLFontScale::GLFONT_SCALE_NORMAL; + +std::mutex GLFont::g_userFontZoomMappingMutex; + GLFontChar::GLFontChar() : id(0), x(0), y(0), width(0), height(0), xoffset(0), yoffset(0), xadvance(0), aspect(1), index(0) { @@ -114,9 +150,12 @@ int GLFontChar::getIndex() { return index; } -GLFont::GLFont() : +GLFont::GLFont(GLFontSize size, std::wstring fontFileName): lineHeight(0), base(0), imageWidth(0), imageHeight(0), loaded(false), texId(0), gcCounter(0) { + fontSizeClass = size; + //relative path to RES_FOLDER + fontFileSource = fontFileName; } GLFont::~GLFont() { @@ -167,8 +206,14 @@ std::wstring GLFont::getParamValue(const std::wstring& param_str) { return value; } -void GLFont::loadFont(const std::wstring& fontFile) { - +void GLFont::loadFontOnce() { + + if (loaded) { + return; + } + + std::wstring fontFile = fontFileSource; + wxString resourceFolder = RES_FOLDER; #ifdef WIN32 @@ -183,6 +228,7 @@ void GLFont::loadFont(const std::wstring& fontFile) { resourceFolder = exePath.GetPath(); } + //overwrite with the full path fontFileSource = fontFileName.GetFullPath(wxPATH_NATIVE).ToStdWstring(); if (!fontFileName.FileExists()) { @@ -405,10 +451,8 @@ void GLFont::loadFont(const std::wstring& fontFile) { } input.close(); -} -bool GLFont::isLoaded() { - return loaded; + loaded = true; } float GLFont::getStringWidth(const std::wstring& str, float size, float viewAspect) { @@ -443,8 +487,12 @@ float GLFont::getStringWidth(const std::wstring& str, float size, float viewAspe // Draw string, immediate void GLFont::drawString(const std::wstring& str, float xpos, float ypos, int pxHeight, Align hAlign, Align vAlign, int vpx, int vpy, bool cacheable) { - + + // Why another scale ? pxHeight *= 2; + + //Rise the pixel hight by the scale factor + pxHeight *= getScaleFactor(); if (!vpx || !vpy) { GLint vp[4]; @@ -459,6 +507,7 @@ void GLFont::drawString(const std::wstring& str, float xpos, float ypos, int pxH std::lock_guard lock(cache_busy); if (gcCounter > 50) { + doCacheGC(); gcCounter = 0; } @@ -639,6 +688,7 @@ void GLFont::drawCacheString(GLFontStringCache *fc, float xpos, float ypos, Alig // Compile optimized GLFontCacheString GLFontStringCache *GLFont::cacheString(const std::wstring& str, int pxHeight, int vpx, int vpy) { + GLFontStringCache *fc = new GLFontStringCache; fc->pxHeight = pxHeight; @@ -711,43 +761,108 @@ void GLFont::doCacheGC() { for (cache_iter = stringCache.begin(); cache_iter != stringCache.end(); cache_iter++) { if (cache_iter->second->gc < -10) { // std::cout << "gc'd " << cache_iter->first << std::endl; + delete cache_iter->second; stringCache.erase(cache_iter); return; } } } +void GLFont::flushGC() { + std::map::iterator cache_iter; + + cache_iter = stringCache.begin(); + + while (cache_iter != stringCache.end()) { + + delete cache_iter->second; + cache_iter = stringCache.erase(cache_iter); + + } +} + GLFont &GLFont::getFont(GLFontSize esize) { - if (!fonts[esize].isLoaded()) { - - std::wstring fontName; - switch (esize) { - case GLFONT_SIZE12: - fontName = L"vera_sans_mono12.fnt"; - break; - case GLFONT_SIZE16: - fontName = L"vera_sans_mono16.fnt"; - break; - case GLFONT_SIZE18: - fontName = L"vera_sans_mono18.fnt"; - break; - case GLFONT_SIZE24: - fontName = L"vera_sans_mono24.fnt"; - break; - case GLFONT_SIZE32: - fontName = L"vera_sans_mono32.fnt"; - break; - case GLFONT_SIZE48: - fontName = L"vera_sans_mono48.fnt"; - break; - default: - fontName = L"vera_sans_mono12.fnt"; - break; - } - - fonts[esize].loadFont(fontName); - } - - return fonts[esize]; + + //really load the internal font instead! + + std::lock_guard lock(g_userFontZoomMappingMutex); + + GLFontSize internalFontSize = userFontZoomMapping[esize]; + + //load lazily... + fonts[internalFontSize].loadFontOnce(); + + return fonts[internalFontSize]; } + + +void GLFont::setScale(GLFontScale scale) { + + //By default, populate with normal font (1:1 matching) then overrides + //0) Normal: + std::lock_guard lock(g_userFontZoomMappingMutex); + + currentScaleFactor = scale; + + userFontZoomMapping[GLFont::GLFONT_SIZE12] = GLFont::GLFONT_SIZE12; + userFontZoomMapping[GLFont::GLFONT_SIZE16] = GLFont::GLFONT_SIZE16; + userFontZoomMapping[GLFont::GLFONT_SIZE18] = GLFont::GLFONT_SIZE18; + userFontZoomMapping[GLFont::GLFONT_SIZE22] = GLFont::GLFONT_SIZE22; + userFontZoomMapping[GLFont::GLFONT_SIZE24] = GLFont::GLFONT_SIZE24; + userFontZoomMapping[GLFont::GLFONT_SIZE32] = GLFont::GLFONT_SIZE32; + userFontZoomMapping[GLFont::GLFONT_SIZE36] = GLFont::GLFONT_SIZE36; + userFontZoomMapping[GLFont::GLFONT_SIZE42] = GLFont::GLFONT_SIZE42; + userFontZoomMapping[GLFont::GLFONT_SIZE48] = GLFont::GLFONT_SIZE48; + userFontZoomMapping[GLFont::GLFONT_SIZE64] = GLFont::GLFONT_SIZE64; + userFontZoomMapping[GLFont::GLFONT_SIZE96] = GLFont::GLFONT_SIZE96; + + //override depending of zoom level: + //Medium : more or less 1.333 x + if (currentScaleFactor == GLFontScale::GLFONT_SCALE_MEDIUM) { + + userFontZoomMapping[GLFont::GLFONT_SIZE12] = GLFont::GLFONT_SIZE16; + userFontZoomMapping[GLFont::GLFONT_SIZE16] = GLFont::GLFONT_SIZE22; + userFontZoomMapping[GLFont::GLFONT_SIZE18] = GLFont::GLFONT_SIZE24; + userFontZoomMapping[GLFont::GLFONT_SIZE22] = GLFont::GLFONT_SIZE32; + userFontZoomMapping[GLFont::GLFONT_SIZE24] = GLFont::GLFONT_SIZE32; + userFontZoomMapping[GLFont::GLFONT_SIZE32] = GLFont::GLFONT_SIZE42; + userFontZoomMapping[GLFont::GLFONT_SIZE36] = GLFont::GLFONT_SIZE48; + userFontZoomMapping[GLFont::GLFONT_SIZE42] = GLFont::GLFONT_SIZE64; + userFontZoomMapping[GLFont::GLFONT_SIZE48] = GLFont::GLFONT_SIZE64; + + } + //Large : 2x normal, more or less + else if (currentScaleFactor == GLFontScale::GLFONT_SCALE_LARGE) { + + userFontZoomMapping[GLFont::GLFONT_SIZE12] = GLFont::GLFONT_SIZE24; + userFontZoomMapping[GLFont::GLFONT_SIZE16] = GLFont::GLFONT_SIZE32; + userFontZoomMapping[GLFont::GLFONT_SIZE18] = GLFont::GLFONT_SIZE36; + userFontZoomMapping[GLFont::GLFONT_SIZE22] = GLFont::GLFONT_SIZE42; + userFontZoomMapping[GLFont::GLFONT_SIZE24] = GLFont::GLFONT_SIZE48; + userFontZoomMapping[GLFont::GLFONT_SIZE32] = GLFont::GLFONT_SIZE64; + userFontZoomMapping[GLFont::GLFONT_SIZE36] = GLFont::GLFONT_SIZE64; + userFontZoomMapping[GLFont::GLFONT_SIZE42] = GLFont::GLFONT_SIZE96; + userFontZoomMapping[GLFont::GLFONT_SIZE48] = GLFont::GLFONT_SIZE96; + } + + //Not overridden mapping stays normal, like the biggest fonts. + + //Note that there is no need to flush the GC, no longer used fonts will be purged auto-magically by aging, + //and the new fonts will show up. +} + +double GLFont::getScaleFactor() { + + if (currentScaleFactor == GLFONT_SCALE_MEDIUM) { + + return 1.33333; + } + else if (currentScaleFactor == GLFONT_SCALE_LARGE) { + + return 2.0; + } + + return 1.0; +} + diff --git a/src/util/GLFont.h b/src/util/GLFont.h index df02a35..ac074ca 100644 --- a/src/util/GLFont.h +++ b/src/util/GLFont.h @@ -59,7 +59,7 @@ public: int getIndex(); private: - // this is the code point of the 16bit character, supposely Unicode. + // this is the code point of the 16bit character, supposly Unicode. int id; int x, y, width, height; int xoffset, yoffset; @@ -74,16 +74,40 @@ public: GLFONT_ALIGN_LEFT, GLFONT_ALIGN_RIGHT, GLFONT_ALIGN_CENTER, GLFONT_ALIGN_TOP, GLFONT_ALIGN_BOTTOM }; enum GLFontSize { - GLFONT_SIZE12, GLFONT_SIZE16, GLFONT_SIZE18, GLFONT_SIZE24, GLFONT_SIZE32, GLFONT_SIZE48, GLFONT_MAX + GLFONT_SIZE12, + GLFONT_SIZE16, + GLFONT_SIZE18, + GLFONT_SIZE22, //new + GLFONT_SIZE24, + GLFONT_SIZE32, + GLFONT_SIZE36, //new + GLFONT_SIZE42, //new + GLFONT_SIZE48, + GLFONT_SIZE64, //new + GLFONT_SIZE96, //new + GLFONT_SIZE_MAX }; - GLFont(); + enum GLFontScale { + GLFONT_SCALE_NORMAL, + GLFONT_SCALE_MEDIUM, // x1.33 + GLFONT_SCALE_LARGE, // x2 + GLFONT_SCALE_MAX + }; + + GLFont(GLFontSize size, std::wstring fontFileName); ~GLFont(); - void loadFont(const std::wstring& fontFile); + //The User request a font to display, but internally + //it will be translated to another font depending of the scale level + static GLFont& getFont(GLFontSize esize); + + //Called to change the scale of the rendered fonts + static void setScale(GLFontScale scale); + + //Return the current scale factor in use (1.0 for normal, 1.333 for medium, 2.0 for large for ex.) + static double getScaleFactor(); - static GLFont &getFont(GLFontSize esize); - //Public drawing font, 16 bit char version. void drawString(const std::wstring& str, float xpos, float ypos, int pxHeight, Align hAlign = GLFONT_ALIGN_LEFT, Align vAlign = GLFONT_ALIGN_TOP, int vpx=0, int vpy=0, bool cacheable = false); @@ -96,26 +120,36 @@ private: std::wstring getParamKey(const std::wstring& param_str); std::wstring getParamValue(const std::wstring& param_str); - - static GLFont fonts[GLFONT_MAX]; - + //Repository of all loaded fonts + static GLFont fonts[GLFontSize::GLFONT_SIZE_MAX]; + + //Map of user requested font to internal font, which changes + //changes with the requested scale. + // this is rebuilt by the user calling setScale(GLFontScale) and changed atomically, + //which map a user-requested font to a final one depending of the zoom level. + static GLFontSize userFontZoomMapping[GLFontSize::GLFONT_SIZE_MAX]; + + static GLFontScale currentScaleFactor; + + //load a given font file, (lazy loading) + void loadFontOnce(); GLFontStringCache *cacheString(const std::wstring& str, int pxHeight, int vpx, int vpy); void drawCacheString(GLFontStringCache *fc, float xpos, float ypos, Align hAlign, Align vAlign); void doCacheGC(); - + void flushGC(); - bool isLoaded(); - float getStringWidth(const std::wstring& str, float size, float viewAspect); + //the string cache is per-front (internal font) std::map stringCache; int lineHeight; int base; int imageWidth, imageHeight; bool loaded; + GLFontSize fontSizeClass; std::map characters; @@ -128,4 +162,6 @@ private: GLuint texId; int gcCounter; std::mutex cache_busy; + + static std::mutex g_userFontZoomMappingMutex; };