SmallWindow on Windows: Recreate fonts when DPI changes, fixing the worst overlap issues.

This commit is contained in:
Henrik Rydgård 2017-01-17 17:57:32 +07:00
parent 0be02f6de0
commit a1016b646e
2 changed files with 46 additions and 20 deletions

View file

@ -41,8 +41,32 @@ enum {
MAX_TEXT_HEIGHT = 512
};
struct TextDrawerFontContext {
class TextDrawerFontContext {
public:
~TextDrawerFontContext() {
Destroy();
}
void Create() {
if (hFont) {
Destroy();
}
// TODO: Should the 72 really be 96? Oh well...
int nHeight = -MulDiv(height, g_dpi, 72);
hFont = CreateFont(nHeight, 0, 0, 0, bold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
VARIABLE_PITCH, fname.c_str());
}
void Destroy() {
DeleteObject(hFont);
hFont = 0;
}
HFONT hFont;
std::wstring fname;
int height;
int bold;
};
struct TextDrawerContext {
@ -78,15 +102,10 @@ TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(nullpt
TextDrawer::~TextDrawer() {
ClearCache();
for (auto iter = fontMap_.begin(); iter != fontMap_.end(); ++iter) {
DeleteObject(iter->second->hFont);
delete iter->second;
}
fontMap_.clear();
DeleteObject(ctx_->hbmBitmap);
DeleteDC(ctx_->hDC);
delete ctx_;
}
@ -108,17 +127,12 @@ uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) {
fname = L"Tahoma";
TextDrawerFontContext *font = new TextDrawerFontContext();
font->bold = FW_LIGHT;
font->height = size;
font->fname = fname;
font->Create();
float textScale = 1.0f;
// TODO: Should the 72 really be 96? Oh well...
INT nHeight = -MulDiv( size, (INT)(GetDeviceCaps(ctx_->hDC, LOGPIXELSY) * textScale), 72 );
int dwBold = FW_LIGHT; ///FW_BOLD
font->hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
VARIABLE_PITCH, fname.c_str());
fontMap_[fontHash] = font;
fontMap_[fontHash] = std::unique_ptr<TextDrawerFontContext>(font);
fontHash_ = fontHash;
return fontHash;
}
@ -292,6 +306,12 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
target.Flush(true);
}
void TextDrawer::RecreateFonts() {
for (auto &iter : fontMap_) {
iter.second->Create();
}
}
#else
TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(NULL) {
@ -331,6 +351,10 @@ void TextDrawer::SetFont(uint32_t fontHandle) {
}
void TextDrawer::RecreateFonts() {
}
void TextDrawer::MeasureString(const char *str, float *w, float *h) {
MeasureString(str, strlen(str), w, h);
}
@ -480,6 +504,7 @@ void TextDrawer::OncePerFrame() {
if (g_dpi_scale != last_dpi_scale_) {
last_dpi_scale_ = g_dpi_scale;
ClearCache();
RecreateFonts();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms

View file

@ -46,7 +46,7 @@ enum {
// Internal struct but all details in .cpp file (pimpl to avoid pulling in excessive headers here)
struct TextDrawerContext;
struct TextDrawerFontContext;
class TextDrawerFontContext;
class TextDrawer {
public:
@ -69,6 +69,7 @@ private:
Draw::DrawContext *thin3d_;
void ClearCache();
void RecreateFonts(); // On DPI change
void WrapString(std::string &out, const char *str, float maxWidth);
int frameCount_;
@ -80,11 +81,11 @@ private:
#ifdef USING_QT_UI
std::map<uint32_t, QFont *> fontMap_;
#else
std::map<uint32_t, TextDrawerFontContext *> fontMap_;
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;
#endif
uint32_t fontHash_;
// The key is the CityHash of the string xor the fontHash_.
std::map<uint32_t, std::unique_ptr<TextStringEntry> > cache_;
std::map<uint32_t, std::unique_ptr<TextMeasureEntry> > sizeCache_;
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
};