From db573c8742e928dd45f3f5e4b933a94d03715029 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sun, 16 Apr 2023 23:14:03 +0100 Subject: [PATCH] Fix #10660: Sprite Font scale affected by viewport zoom level limits. (#10668) --- src/fontcache/spritefontcache.cpp | 16 +++++++++++++--- src/gfx.cpp | 18 ++++++++++++------ src/spritecache.cpp | 27 ++++++++++++++++++++------- src/spritecache.h | 1 + src/spriteloader/grf.cpp | 5 +++-- src/zoom_type.h | 1 + 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/fontcache/spritefontcache.cpp b/src/fontcache/spritefontcache.cpp index ec7a969174..7dbb777de3 100644 --- a/src/fontcache/spritefontcache.cpp +++ b/src/fontcache/spritefontcache.cpp @@ -21,6 +21,16 @@ static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter. +/** + * Scale traditional pixel dimensions to font zoom level, for drawing sprite fonts. + * @param value Pixel amount at #ZOOM_LVL_BASE (traditional "normal" interface size). + * @return Pixel amount at _font_zoom (current interface size). + */ +static int ScaleFontTrad(int value) +{ + return UnScaleByZoom(value * ZOOM_LVL_BASE, _font_zoom); +} + /** * Create a new sprite font cache. * @param fs The font size to create the cache for. @@ -29,7 +39,7 @@ SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs), glyph_to_spriteid { this->InitializeUnicodeGlyphMap(); this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs)); - this->ascender = (this->height - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2; + this->ascender = (this->height - ScaleFontTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2; } /** @@ -106,7 +116,7 @@ void SpriteFontCache::ClearFontCache() { Layouter::ResetFontCache(this->fs); this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs)); - this->ascender = (this->height - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2; + this->ascender = (this->height - ScaleFontTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2; } const Sprite *SpriteFontCache::GetGlyph(GlyphID key) @@ -120,7 +130,7 @@ uint SpriteFontCache::GetGlyphWidth(GlyphID key) { SpriteID sprite = this->GetUnicodeGlyph(key); if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); - return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleSpriteTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; + return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; } bool SpriteFontCache::GetDrawGlyphShadow() diff --git a/src/gfx.cpp b/src/gfx.cpp index b2d0df5c15..8799bdbc95 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -61,9 +61,10 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, static ReusableBuffer _cursor_backup; -ZoomLevel _gui_zoom = ZOOM_LVL_OUT_4X; ///< GUI Zoom level -int _gui_scale = MIN_INTERFACE_SCALE; ///< GUI scale, 100 is 100%. -int _gui_scale_cfg; ///< GUI scale in config. +ZoomLevel _gui_zoom = ZOOM_LVL_OUT_4X; ///< GUI Zoom level +ZoomLevel _font_zoom = _gui_zoom; ///< Sprite font Zoom level (not clamped) +int _gui_scale = MIN_INTERFACE_SCALE; ///< GUI scale, 100 is 100%. +int _gui_scale_cfg; ///< GUI scale in config. /** * The rect for repaint. @@ -2049,6 +2050,8 @@ void UpdateGUIZoom() } int8 new_zoom = ScaleGUITrad(1) <= 1 ? ZOOM_LVL_OUT_4X : ScaleGUITrad(1) >= 4 ? ZOOM_LVL_MIN : ZOOM_LVL_OUT_2X; + /* Font glyphs should not be clamped to min/max zoom. */ + _font_zoom = static_cast(new_zoom); /* Ensure the gui_zoom is clamped between min/max. */ new_zoom = Clamp(new_zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max); _gui_zoom = static_cast(new_zoom); @@ -2062,16 +2065,19 @@ void UpdateGUIZoom() */ bool AdjustGUIZoom(bool automatic) { - ZoomLevel old_zoom = _gui_zoom; + ZoomLevel old_gui_zoom = _gui_zoom; + ZoomLevel old_font_zoom = _font_zoom; int old_scale = _gui_scale; UpdateGUIZoom(); if (old_scale == _gui_scale) return false; /* Reload sprites if sprite zoom level has changed. */ - if (old_zoom != _gui_zoom) { + if (old_gui_zoom != _gui_zoom) { GfxClearSpriteCache(); VideoDriver::GetInstance()->ClearSystemSprites(); UpdateCursorSize(); + } else if (old_font_zoom != _font_zoom) { + GfxClearFontSpriteCache(); } ClearFontCache(); @@ -2080,7 +2086,7 @@ bool AdjustGUIZoom(bool automatic) /* Adjust all window sizes to match the new zoom level, so that they don't appear to move around when the application is moved to a screen with different DPI. */ - auto zoom_shift = old_zoom - _gui_zoom; + auto zoom_shift = old_gui_zoom - _gui_zoom; for (Window *w : Window::Iterate()) { if (automatic) { w->left = (w->left * _gui_scale) / old_scale; diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 5cf34ba924..7159719c65 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -519,14 +519,14 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty return (void*)GetRawSprite(SPR_IMG_QUERY, SpriteType::Normal, allocator, encoder); } - if (sprite->type == SpriteType::Font && ZOOM_LVL_GUI != ZOOM_LVL_NORMAL) { + if (sprite->type == SpriteType::Font && _font_zoom != ZOOM_LVL_NORMAL) { /* Make ZOOM_LVL_NORMAL be ZOOM_LVL_GUI */ - sprite[ZOOM_LVL_NORMAL].width = sprite[ZOOM_LVL_GUI].width; - sprite[ZOOM_LVL_NORMAL].height = sprite[ZOOM_LVL_GUI].height; - sprite[ZOOM_LVL_NORMAL].x_offs = sprite[ZOOM_LVL_GUI].x_offs; - sprite[ZOOM_LVL_NORMAL].y_offs = sprite[ZOOM_LVL_GUI].y_offs; - sprite[ZOOM_LVL_NORMAL].data = sprite[ZOOM_LVL_GUI].data; - sprite[ZOOM_LVL_NORMAL].colours = sprite[ZOOM_LVL_GUI].colours; + sprite[ZOOM_LVL_NORMAL].width = sprite[_font_zoom].width; + sprite[ZOOM_LVL_NORMAL].height = sprite[_font_zoom].height; + sprite[ZOOM_LVL_NORMAL].x_offs = sprite[_font_zoom].x_offs; + sprite[ZOOM_LVL_NORMAL].y_offs = sprite[_font_zoom].y_offs; + sprite[ZOOM_LVL_NORMAL].data = sprite[_font_zoom].data; + sprite[ZOOM_LVL_NORMAL].colours = sprite[_font_zoom].colours; } return encoder->Encode(sprite, allocator); @@ -1048,4 +1048,17 @@ void GfxClearSpriteCache() VideoDriver::GetInstance()->ClearSystemSprites(); } +/** + * Remove all encoded font sprites from the sprite cache without + * discarding sprite location information. + */ +void GfxClearFontSpriteCache() +{ + /* Clear sprite ptr for all cached font items */ + for (uint i = 0; i != _spritecache_items; i++) { + SpriteCache *sc = GetSpriteCache(i); + if (sc->type == SpriteType::Font && sc->ptr != nullptr) DeleteEntryFromSpriteCache(i); + } +} + /* static */ ReusableBuffer SpriteLoader::Sprite::buffer[ZOOM_LVL_COUNT]; diff --git a/src/spritecache.h b/src/spritecache.h index c7c27c487e..52ebe68c25 100644 --- a/src/spritecache.h +++ b/src/spritecache.h @@ -58,6 +58,7 @@ static inline const byte *GetNonSprite(SpriteID sprite, SpriteType type) void GfxInitSpriteMem(); void GfxClearSpriteCache(); +void GfxClearFontSpriteCache(); void IncreaseSpriteLRU(); SpriteFile &OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap); diff --git a/src/spriteloader/grf.cpp b/src/spriteloader/grf.cpp index af386e1f90..bb678b053d 100644 --- a/src/spriteloader/grf.cpp +++ b/src/spriteloader/grf.cpp @@ -282,11 +282,12 @@ uint8 LoadSpriteV2(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_p if (sprite_type != SpriteType::MapGen) { if (zoom < lengthof(zoom_lvl_map)) { is_wanted_zoom_lvl = true; - if (_settings_client.gui.sprite_zoom_min >= ZOOM_LVL_OUT_2X && + ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZOOM_LVL_NORMAL : _settings_client.gui.sprite_zoom_min; + if (zoom_min >= ZOOM_LVL_OUT_2X && HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl_map[zoom] < ZOOM_LVL_OUT_2X) { is_wanted_zoom_lvl = false; } - if (_settings_client.gui.sprite_zoom_min >= ZOOM_LVL_OUT_4X && + if (zoom_min >= ZOOM_LVL_OUT_4X && HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl_map[zoom] < ZOOM_LVL_OUT_4X) { is_wanted_zoom_lvl = false; } diff --git a/src/zoom_type.h b/src/zoom_type.h index 7ccc142ef3..ab2e24b7b5 100644 --- a/src/zoom_type.h +++ b/src/zoom_type.h @@ -52,6 +52,7 @@ extern int _gui_scale; extern int _gui_scale_cfg; extern ZoomLevel _gui_zoom; +extern ZoomLevel _font_zoom; #define ZOOM_LVL_GUI (_gui_zoom) static const int MIN_INTERFACE_SCALE = 100;