blizzget/src/frameui/fontsys.cpp
2016-03-09 11:42:26 +03:00

172 lines
5.4 KiB
C++

#include "fontsys.h"
#include <algorithm>
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);
}