diff --git a/src/driver/neutrinofonts.cpp b/src/driver/neutrinofonts.cpp index 8c7e0c360..93e34f32d 100644 --- a/src/driver/neutrinofonts.cpp +++ b/src/driver/neutrinofonts.cpp @@ -3,6 +3,9 @@ Copyright (C) 2001 Steffen Hehn 'McClean' + CNeutrinoFonts class for gui. + Copyright (C) 2013, M. Liebmann (micha-bbg) + License: GPL This program is free software; you can redistribute it and/or @@ -48,11 +51,39 @@ const font_sizes_struct signal_font = {LOCALE_FONTSIZE_INFOBAR_SMALL, 14, CNeutr CNeutrinoFonts::CNeutrinoFonts() { + useDigitOffset = false; memset(&fontDescr, 0, sizeof(neutrino_font_descr_struct)); + InitDynFonts(); +} + +void CNeutrinoFonts::InitDynFonts() +{ + for (int i = 0; i < FONT_ID_MAX; i++) { + dyn_font_t dyn_font; + dyn_font.dx = 0; + dyn_font.dy = 0; + dyn_font.size = 0; + dyn_font.style = 0; + dyn_font.text = ""; + dyn_font.font = NULL; + dyn_font.useDigitOffset = false; + v_dyn_fonts.push_back(dyn_font); + } } CNeutrinoFonts::~CNeutrinoFonts() { + if (!v_share_fonts.empty()) { + for (unsigned int i = 0; i < v_share_fonts.size(); i++) + delete v_share_fonts[i].font; + v_share_fonts.clear(); + } + + if (!v_dyn_fonts.empty()) { + for (unsigned int i = 0; i < v_dyn_fonts.size(); i++) + delete v_dyn_fonts[i].font; + v_dyn_fonts.clear(); + } } CNeutrinoFonts* CNeutrinoFonts::getInstance() @@ -100,3 +131,218 @@ void CNeutrinoFonts::SetupNeutrinoFonts() } g_SignalFont = g_fontRenderer->getFont(fontDescr.name, fontStyle[signal_font.style], signal_font.defaultsize + signal_font.size_offset * fontDescr.size_offset); } + +void CNeutrinoFonts::refreshDynFonts() +{ + if (!v_share_fonts.empty()) { + for (unsigned int i = 0; i < v_share_fonts.size(); i++) { + if (v_share_fonts[i].font != NULL) + refreshDynFont(v_share_fonts[i].dx, v_share_fonts[i].dy, v_share_fonts[i].text, v_share_fonts[i].style, i, true); + } + } + + if (!v_dyn_fonts.empty()) { + for (unsigned int i = 0; i < v_dyn_fonts.size(); i++) { + if (v_dyn_fonts[i].font != NULL) + refreshDynFont(v_dyn_fonts[i].dx, v_dyn_fonts[i].dy, v_dyn_fonts[i].text, v_dyn_fonts[i].style, i, false); + } + } +} + +void CNeutrinoFonts::refreshDynFont(int dx, int dy, std::string text, int style, int index, bool isShare) +{ + if ((dx <= 0) && (dy <= 0)) + return; + + dyn_font_t *dyn_font = (isShare) ? &(v_share_fonts[index]) : &(v_dyn_fonts[index]); + int oldSize = dyn_font->size; + bool tmp = useDigitOffset; + useDigitOffset = dyn_font->useDigitOffset; + int dynSize = getDynFontSize(dx, dy, text, style); + useDigitOffset = tmp; + if (dyn_font->size == dynSize) + return; + + if (dyn_font->font != NULL) + delete dyn_font->font; + Font *dynFont = g_fontRenderer->getFont(fontDescr.name, fontStyle[style], dynSize); + dyn_font->font = dynFont; + dyn_font->size = dynSize; + printf("##### [%s] change %s_font size old %d to new %d, index: %u\n", __FUNCTION__, (isShare)?"share":"dyn", oldSize, dyn_font->size, index); +} + +int CNeutrinoFonts::getFontHeight(Font* fnt) +{ + if (useDigitOffset) + return fnt->getDigitHeight() + (fnt->getDigitOffset() * 18) / 10; + else + return fnt->getHeight(); +} + +int CNeutrinoFonts::getDynFontSize(int dx, int dy, std::string text, int style) +{ + Font *dynFont = NULL; + int _width = 0; + int _height = 0; + int dynSize = 8; + bool dynFlag = false; + + if (dx == 0) dx = 1280; + while (1) { + if (dynFont != NULL) + delete dynFont; + dynFont = g_fontRenderer->getFont(fontDescr.name, fontStyle[style], dynSize); + // calculate height & width + _height = getFontHeight(dynFont); + std::string tmpText = text; + if (text == "") tmpText = "x"; + _width = dynFont->getRenderWidth(tmpText.c_str()); + if ((_height > dy) || (_width > dx)) { + if (dynFlag) + dynSize--; + else + printf("##### [%s] Specified size (dx=%d, dy=%d) too small, use minimal font size.\n", __FUNCTION__, dx, dy); + break; + } + else if ((_height < dy) || (_width < dx)) { + dynFlag = true; + dynSize++; + } + else + break; + } + + if (dynFont != NULL) + delete dynFont; + + return dynSize; +} + +/* CNeutrinoFonts::getDynFont usage + + * dx, dy max. width/height of text field / return: real width/height of text field + If dx = 0, then the width is calculated automatically + + * text Text to display + If text = "", then only the height is calculated + + * style Font style (FONT_STYLE_REGULAR or FONT_STYLE_BOLD or FONT_STYLE_ITALIC) + + * share Select font modus + FONT_ID_SHARE Font for used by several objects simultaneously + FONT_ID_xxx Font for exclusive application + FONT_ID_yyy - "" - + FONT_ID_zzz - "" - + + * return value: Pointer to dynamic font + + example: + dx = 0; //dx = 0, width is calculated automatically + dy = 30; //max. height + text = "100"; //max. text to display + //CNeutrinoFonts::FONT_STYLE_REGULAR = normal font style + //CNeutrinoFonts::FONT_ID_VOLBAR = exclusive font for Volume bar (defined in src/driver/neutrinofonts.h) + Font** font = CNeutrinoFonts::getInstance()->getDynFont(dx, dy, text, CNeutrinoFonts::FONT_STYLE_REGULAR, CNeutrinoFonts::FONT_ID_VOLBAR); + (*font)->RenderString(...) + +*/ +Font **CNeutrinoFonts::getDynFont(int &dx, int &dy, std::string text/*=""*/, int style/*=FONT_STYLE_REGULAR*/, int share/*=FONT_ID_SHARE*/) +{ + if (share > FONT_ID_SHARE) + return getDynFontWithID(dx, dy, text, style, share); + else + return getDynFontShare(dx, dy, text, style); +} + +Font **CNeutrinoFonts::getDynFontWithID(int &dx, int &dy, std::string text, int style, unsigned int f_id) +{ + if ((dx <= 0) && (dy <= 0)) + return NULL; + if ((fontDescr.name == NULL) || (fontDescr.filename == NULL) || (g_fontRenderer == NULL)) + SetupNeutrinoFonts(); + + int dynSize = getDynFontSize(dx, dy, text, style); + Font *dynFont = NULL; + Font **ret = NULL; + + if (f_id < v_dyn_fonts.size()) { + if ((v_dyn_fonts[f_id].size == dynSize) && (v_dyn_fonts[f_id].font != NULL)) { + dy = v_dyn_fonts[f_id].font->getHeight(); + if (text != "") + dx = v_dyn_fonts[f_id].font->getRenderWidth(text.c_str()); + return &(v_dyn_fonts[f_id].font); + } + + dynFont = g_fontRenderer->getFont(fontDescr.name, fontStyle[style], dynSize); + if (v_dyn_fonts[f_id].font != NULL) + delete v_dyn_fonts[f_id].font; + v_dyn_fonts[f_id].dx = dx; + v_dyn_fonts[f_id].dy = dy; + v_dyn_fonts[f_id].size = dynSize; + v_dyn_fonts[f_id].style = style; + v_dyn_fonts[f_id].text = text; + v_dyn_fonts[f_id].font = dynFont; + v_dyn_fonts[f_id].useDigitOffset = useDigitOffset; + ret = &(v_dyn_fonts[f_id].font); + } + else + return NULL; + + dy = (*ret)->getHeight(); + if (text != "") + dx = (*ret)->getRenderWidth(text.c_str()); + printf("##### [%s] dx: %d, dy: %d, dynSize: %d, dynFont: %p, ret: %p, FontID: %d\n", __FUNCTION__, dx, dy, dynSize, *ret, ret, f_id); + return ret; +} + +Font **CNeutrinoFonts::getDynFontShare(int &dx, int &dy, std::string text, int style) +{ + if ((dx <= 0) && (dy <= 0)) + return NULL; + if ((fontDescr.name == NULL) || (fontDescr.filename == NULL) || (g_fontRenderer == NULL)) + SetupNeutrinoFonts(); + + int dynSize = getDynFontSize(dx, dy, text, style); + Font *dynFont = NULL; + + bool fontAvailable = false; + unsigned int i; + Font **ret = NULL; + if (!v_share_fonts.empty()) { + for (i = 0; i < v_share_fonts.size(); i++) { + if ((v_share_fonts[i].size == dynSize) && + (v_share_fonts[i].style == style) && + (v_share_fonts[i].useDigitOffset == useDigitOffset)) { + fontAvailable = true; + break; + } + } + } + if (fontAvailable) { + if (text.length() > v_share_fonts[i].text.length()) { + v_share_fonts[i].dx = dx; + v_share_fonts[i].dy = dy; + v_share_fonts[i].text = text; + } + ret = &(v_share_fonts[i].font); + } + else { + dynFont = g_fontRenderer->getFont(fontDescr.name, fontStyle[style], dynSize); + dyn_font_t dyn_font; + dyn_font.dx = dx; + dyn_font.dy = dy; + dyn_font.size = dynSize; + dyn_font.style = style; + dyn_font.text = text; + dyn_font.font = dynFont; + dyn_font.useDigitOffset = useDigitOffset; + v_share_fonts.push_back(dyn_font); + ret = &(v_share_fonts[v_share_fonts.size()-1].font); + } + + dy = (*ret)->getHeight(); + if (text != "") + dx = (*ret)->getRenderWidth(text.c_str()); + printf("##### [%s] dx: %d, dy: %d, dynSize: %d, dynFont: %p, ret: %p, fontAvailable: %d\n", __FUNCTION__, dx, dy, dynSize, *ret, ret, fontAvailable); + return ret; +} diff --git a/src/driver/neutrinofonts.h b/src/driver/neutrinofonts.h index 4e0dce68f..53b6952df 100644 --- a/src/driver/neutrinofonts.h +++ b/src/driver/neutrinofonts.h @@ -3,6 +3,9 @@ Copyright (C) 2001 Steffen Hehn 'McClean' + CNeutrinoFonts class for gui. + Copyright (C) 2013, M. Liebmann (micha-bbg) + License: GPL This program is free software; you can redistribute it and/or @@ -50,6 +53,29 @@ class CNeutrinoFonts private: const char * fontStyle[3]; + typedef struct dyn_font_t + { + int dx; + int dy; + int size; + int style; + std::string text; + Font* font; + bool useDigitOffset; + } dyn_font_struct_t; + + typedef std::vector v_dyn_fonts_t; + v_dyn_fonts_t v_share_fonts; + v_dyn_fonts_t v_dyn_fonts; + bool useDigitOffset; + + void InitDynFonts(); + void refreshDynFont(int dx, int dy, std::string text, int style, int index, bool isShare); + int getFontHeight(Font* fnt); + int getDynFontSize(int dx, int dy, std::string text, int style); + Font **getDynFontShare(int &dx, int &dy, std::string text, int style); + Font **getDynFontWithID(int &dx, int &dy, std::string text, int style, unsigned int f_id); + public: enum { FONT_STYLE_REGULAR = 0, @@ -57,6 +83,15 @@ class CNeutrinoFonts FONT_STYLE_ITALIC = 2 }; + enum { + FONT_ID_SHARE = -1 + }; + enum { + FONT_ID_xxx, + + FONT_ID_MAX + }; + CNeutrinoFonts(); ~CNeutrinoFonts(); static CNeutrinoFonts* getInstance(); @@ -64,6 +99,9 @@ class CNeutrinoFonts neutrino_font_descr_struct fontDescr; void SetupNeutrinoFonts(); + void refreshDynFonts(); + Font **getDynFont(int &dx, int &dy, std::string text="", int style=FONT_STYLE_REGULAR, int share=FONT_ID_SHARE); + void setFontUseDigitHeight(bool set=true) {useDigitOffset = set;} }; diff --git a/src/neutrino.cpp b/src/neutrino.cpp index efa262bd8..c14d8f6a3 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -1525,6 +1525,7 @@ void CNeutrinoApp::SetupFonts() if (neutrinoFonts == NULL) neutrinoFonts = CNeutrinoFonts::getInstance(); neutrinoFonts->SetupNeutrinoFonts(); + neutrinoFonts->refreshDynFonts(); /* recalculate infobar position */ if (g_InfoViewer)