#include "fontsys.h" #include FontSys FontSys::instance; //#define MKSIZE(s) (-MulDiv(s,instance.logPixelsY,72)) #define MKSIZE(s) (-(s)) FontSys::FontStruct::FontStruct(LOGFONT const& lf) { font = CreateFontIndirect(&lf); face = lf.lfFaceName; size = lf.lfHeight; flags = 0; if (lf.lfWeight > FW_NORMAL) flags |= FONT_BOLD; if (lf.lfItalic) flags |= FONT_ITALIC; if (lf.lfUnderline) flags |= FONT_UNDERLINE; if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; } bool operator<(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs) { if (lhs.size != rhs.size) return lhs.size < rhs.size; if (lhs.flags != rhs.flags) return lhs.flags < rhs.flags; return lhs.face < rhs.face; } bool operator==(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs) { if (lhs.size != rhs.size) return false; if (lhs.flags != rhs.flags) return false; return lhs.face == rhs.face; } FontSys::FontSys() { LOGFONT lf; memset (&lf, 0, sizeof lf); lf.lfHeight = -11; lf.lfWeight = FW_NORMAL; strcpy(lf.lfFaceName, "MS Shell Dlg 2"); lf.lfCharSet = DEFAULT_CHARSET; fonts.emplace_back(lf); hDC = CreateCompatibleDC(NULL); logPixelsY = GetDeviceCaps(hDC, LOGPIXELSY); } FontSys::~FontSys() { DeleteDC(hDC); } HFONT FontSys::getSysFont() { return instance.fonts[0].font; } HFONT FontSys::_getFont(int height, std::string const& face, int flags) { FontStruct fs; fs.size = height; fs.flags = flags; fs.face = face; auto pos = std::lower_bound(fonts.begin() + 1, fonts.end(), fs); if (pos != fonts.end() && *pos == fs) { return pos->font; } LOGFONT lf; getLogFont(&lf, -height, face, flags); return fonts.emplace(pos, lf)->font; } void FontSys::getLogFont(LOGFONT* lf, int size, std::string const& face, int flags) { GetObject(instance.fonts[0].font, sizeof(LOGFONT), lf); lf->lfHeight = MKSIZE(size); strcpy(lf->lfFaceName, face.c_str()); lf->lfWeight = (flags & FONT_BOLD ? FW_BOLD : FW_NORMAL); lf->lfItalic = (flags & FONT_ITALIC ? TRUE : FALSE); lf->lfUnderline = (flags & FONT_UNDERLINE ? TRUE : FALSE); lf->lfStrikeOut = (flags & FONT_STRIKEOUT ? TRUE : FALSE); } HFONT FontSys::getFont(int size, std::string const& face, int flags) { return instance._getFont(MKSIZE(size), face, flags); } HFONT FontSys::getFont(int size, int flags) { return instance._getFont(MKSIZE(size), instance.fonts[0].face, flags); } HFONT FontSys::changeSize(int size, HFONT oldFont) { if (oldFont == NULL) oldFont = getSysFont(); LOGFONT lf; GetObject(oldFont, sizeof lf, &lf); int flags = 0; if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; if (lf.lfItalic) flags |= FONT_ITALIC; if (lf.lfUnderline) flags |= FONT_UNDERLINE; if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; return instance._getFont(MKSIZE(size), lf.lfFaceName, flags); } HFONT FontSys::changeFlags(int flags, HFONT oldFont) { if (oldFont == NULL) oldFont = getSysFont(); LOGFONT lf; GetObject(oldFont, sizeof lf, &lf); return instance._getFont(lf.lfHeight, lf.lfFaceName, flags); } SIZE FontSys::getTextSize(HFONT font, std::string const& text) { SIZE sz; SelectObject(instance.hDC, font); GetTextExtentPoint32(instance.hDC, text.c_str(), text.length(), &sz); return sz; } SIZE FontSys::getTextSize(HFONT font, char const* text, int length) { SIZE sz; SelectObject(instance.hDC, font); GetTextExtentPoint32(instance.hDC, text, length, &sz); return sz; } int FontSys::getMTextHeight(HFONT font, int width, std::string const& text) { SIZE sz; SelectObject(instance.hDC, font); std::string word; std::string curline; int height = 0; for (int i = 0; i <= text.length (); i++) { if (text[i] && text[i] != '\n' && !isspace((uint8)text[i])) { word += text[i]; } if (text[i] == 0 || isspace((uint8) text[i])) { std::string tmp = curline + word; GetTextExtentPoint32(instance.hDC, tmp.c_str(), tmp.length(), &sz); int wd = sz.cx; if (text[i] == '\n' || (wd > width && !curline.empty())) { GetTextExtentPoint32(instance.hDC, curline.c_str(), curline.length(), &sz); height += sz.cy; curline.clear(); } curline += word; if (text[i]) curline += text[i]; word.clear(); } } if (!curline.empty()) { GetTextExtentPoint32(instance.hDC, curline.c_str(), curline.length(), &sz); height += sz.cy; } return height; } int FontSys::getFlags(HFONT font) { if (font == NULL) font = getSysFont(); LOGFONT lf; GetObject(font, sizeof lf, &lf); int flags = 0; if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; if (lf.lfItalic) flags |= FONT_ITALIC; if (lf.lfUnderline) flags |= FONT_UNDERLINE; if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; return flags; } void FontSys::setFontName(HFONT hFont, std::string const& name) { instance.byName[name] = hFont; } HFONT FontSys::getFontByName(std::string const& name) { auto it = instance.byName.find(name); return (it == instance.byName.end() ? instance.fonts[0].font : it->second); } HFONT FontSys::getFont(LOGFONT const& lf) { int flags = 0; if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; if (lf.lfItalic) flags |= FONT_ITALIC; if (lf.lfUnderline) flags |= FONT_UNDERLINE; if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; return instance._getFont(lf.lfHeight, lf.lfFaceName, flags); }