diff --git a/src/fontcache.h b/src/fontcache.h index e01059dd08..c5a5ff873b 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -65,16 +65,6 @@ public: */ virtual int GetFontSize() const { return this->height; } - /** - * Map a SpriteID to the key - * @param key The key to map to. - * @param sprite The sprite that is being mapped. - */ - virtual void SetUnicodeGlyph(char32_t key, SpriteID sprite) = 0; - - /** Initialize the glyph map */ - virtual void InitializeUnicodeGlyphMap() = 0; - /** Clear the font cache. */ virtual void ClearFontCache() = 0; @@ -148,20 +138,6 @@ public: virtual bool IsBuiltInFont() = 0; }; -/** Map a SpriteID to the font size and key */ -inline void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite) -{ - FontCache::Get(size)->SetUnicodeGlyph(key, sprite); -} - -/** Initialize the glyph map */ -inline void InitializeUnicodeGlyphMap() -{ - for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) { - FontCache::Get(fs)->InitializeUnicodeGlyphMap(); - } -} - inline void ClearFontCache(FontSizes fontsizes) { for (FontSize fs : fontsizes) { @@ -232,4 +208,8 @@ void UninitFontCache(); bool GetFontAAState(); void SetFont(FontSize fontsize, const std::string &font, uint size); +/* Implemented in spritefontcache.cpp */ +void InitializeUnicodeGlyphMap(); +void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite); + #endif /* FONTCACHE_H */ diff --git a/src/fontcache/spritefontcache.cpp b/src/fontcache/spritefontcache.cpp index c9f75153b5..2d46d0f106 100644 --- a/src/fontcache/spritefontcache.cpp +++ b/src/fontcache/spritefontcache.cpp @@ -8,6 +8,7 @@ /** @file spritefontcache.cpp Sprite fontcache implementation. */ #include "../stdafx.h" + #include "../fontcache.h" #include "../gfx_layout.h" #include "../zoom_func.h" @@ -19,7 +20,7 @@ #include "../safeguards.h" -static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter. +static std::array, FS_END> _glyph_maps{}; ///< Glyph map for each font size. /** * Scale traditional pixel dimensions to font zoom level, for drawing sprite fonts. @@ -37,61 +38,23 @@ static int ScaleFontTrad(int value) */ SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs) { - this->InitializeUnicodeGlyphMap(); this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs)); this->ascender = (this->height - ScaleFontTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2; } /** - * Get SpriteID associated with a GlyphID. - * @param key Glyph to find. - * @return SpriteID of glyph, or 0 if not present. + * Get the SpriteID associated with a unicode character. + * @param key Character to find. + * @return SpriteID of character, or 0 if not present. */ -SpriteID SpriteFontCache::GetUnicodeGlyph(GlyphID key) +SpriteID SpriteFontCache::GetSpriteIDForChar(char32_t key) { - const auto found = this->glyph_to_spriteid_map.find(key & ~SPRITE_GLYPH); - if (found == std::end(this->glyph_to_spriteid_map)) return 0; - return found->second; -} + const auto &glyph_map = _glyph_maps[this->fs]; -void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite) -{ - this->glyph_to_spriteid_map[key] = sprite; -} + auto it = glyph_map.find(key); + if (it != std::end(glyph_map)) return it->second; -void SpriteFontCache::InitializeUnicodeGlyphMap() -{ - /* Clear out existing glyph map if it exists */ - this->glyph_to_spriteid_map.clear(); - - SpriteID base; - switch (this->fs) { - default: NOT_REACHED(); - case FS_MONO: // Use normal as default for mono spaced font - case FS_NORMAL: base = SPR_ASCII_SPACE; break; - case FS_SMALL: base = SPR_ASCII_SPACE_SMALL; break; - case FS_LARGE: base = SPR_ASCII_SPACE_BIG; break; - } - - for (uint i = ASCII_LETTERSTART; i < 256; i++) { - SpriteID sprite = base + i - ASCII_LETTERSTART; - if (!SpriteExists(sprite)) continue; - this->SetUnicodeGlyph(i, sprite); - this->SetUnicodeGlyph(i + SCC_SPRITE_START, sprite); - } - - for (const auto &unicode_map : _default_unicode_map) { - uint8_t key = unicode_map.key; - if (key == CLRA) { - /* Clear the glyph. This happens if the glyph at this code point - * is non-standard and should be accessed by an SCC_xxx enum - * entry only. */ - this->SetUnicodeGlyph(unicode_map.code, 0); - } else { - SpriteID sprite = base + key - ASCII_LETTERSTART; - this->SetUnicodeGlyph(unicode_map.code, sprite); - } - } + return 0; } void SpriteFontCache::ClearFontCache() @@ -103,22 +66,22 @@ void SpriteFontCache::ClearFontCache() const Sprite *SpriteFontCache::GetGlyph(GlyphID key) { - SpriteID sprite = this->GetUnicodeGlyph(static_cast(key & ~SPRITE_GLYPH)); - if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); + SpriteID sprite = this->GetSpriteIDForChar(static_cast(key & ~SPRITE_GLYPH)); + if (sprite == 0) sprite = this->GetSpriteIDForChar('?'); return GetSprite(sprite, SpriteType::Font); } uint SpriteFontCache::GetGlyphWidth(GlyphID key) { - SpriteID sprite = this->GetUnicodeGlyph(static_cast(key & ~SPRITE_GLYPH)); - if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); + SpriteID sprite = this->GetSpriteIDForChar(static_cast(key & ~SPRITE_GLYPH)); + if (sprite == 0) sprite = this->GetSpriteIDForChar('?'); return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; } GlyphID SpriteFontCache::MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback) { assert(IsPrintable(key)); - SpriteID sprite = this->GetUnicodeGlyph(key); + SpriteID sprite = this->GetSpriteIDForChar(key); if (sprite == 0) return 0; return SPRITE_GLYPH | key; } @@ -127,3 +90,79 @@ bool SpriteFontCache::GetDrawGlyphShadow() { return false; } + +/** + * Set the SpriteID for a unicode character. + * @param fs Font size to set. + * @param key Unicode character to set. + * @param sprite SpriteID of character. + */ +void SetUnicodeGlyph(FontSize fs, char32_t key, SpriteID sprite) +{ + _glyph_maps[fs][key] = sprite; +} + +/** + * Get the sprite font base sprite index. + * @param fs Font size to get base sprite for. + * @return Base sprite for font. + */ +static SpriteID GetSpriteFontBase(FontSize fs) +{ + switch (fs) { + default: NOT_REACHED(); + case FS_MONO: // Use normal as default for mono spaced font + case FS_NORMAL: return SPR_ASCII_SPACE; + case FS_SMALL: return SPR_ASCII_SPACE_SMALL; + case FS_LARGE: return SPR_ASCII_SPACE_BIG; + } +} + +/** + * Initialize the glyph map for a font size. + * This populates the glyph map with the baseset font sprites. + * @param fs Font size to initialize. + */ +void InitializeUnicodeGlyphMap(FontSize fs) +{ + static constexpr int ASCII_LETTERSTART = 32; ///< First printable ASCII letter. + + /* Clear existing glyph map. */ + _glyph_maps[fs].clear(); + + SpriteID base = GetSpriteFontBase(fs); + for (uint i = ASCII_LETTERSTART; i < 256; i++) { + SpriteID sprite = base + i - ASCII_LETTERSTART; + if (!SpriteExists(sprite)) continue; + + /* Map the glyph for normal use. */ + SetUnicodeGlyph(fs, i, sprite); + + /* Glyphs are also mapped to the first private use area. */ + SetUnicodeGlyph(fs, i + SCC_SPRITE_START, sprite); + } + + /* Modify map to move non-standard glyphs to a better unicode codepoint. */ + for (const auto &unicode_map : _default_unicode_map) { + uint8_t key = unicode_map.key; + if (key == CLRA) { + /* Clear the glyph. This happens if the glyph at this code point + * is non-standard and should be accessed by an SCC_xxx enum + * entry only. */ + _glyph_maps[fs].erase(unicode_map.code); + } else { + SpriteID sprite = base + key - ASCII_LETTERSTART; + SetUnicodeGlyph(fs, unicode_map.code, sprite); + } + } +} + +/** + * Initialize the glyph map. + */ +void InitializeUnicodeGlyphMap() +{ + for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) { + InitializeUnicodeGlyphMap(fs); + } +} diff --git a/src/fontcache/spritefontcache.h b/src/fontcache/spritefontcache.h index 61dd5866e2..fc3d49e4eb 100644 --- a/src/fontcache/spritefontcache.h +++ b/src/fontcache/spritefontcache.h @@ -17,8 +17,6 @@ class SpriteFontCache : public FontCache { public: SpriteFontCache(FontSize fs); - void SetUnicodeGlyph(char32_t key, SpriteID sprite) override; - void InitializeUnicodeGlyphMap() override; void ClearFontCache() override; const Sprite *GetGlyph(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override; @@ -28,8 +26,7 @@ public: bool IsBuiltInFont() override { return true; } private: - std::unordered_map glyph_to_spriteid_map{}; ///< Mapping of glyphs to sprite IDs. - SpriteID GetUnicodeGlyph(GlyphID key); + SpriteID GetSpriteIDForChar(char32_t key); }; #endif /* SPRITEFONTCACHE_H */ diff --git a/src/fontcache/truetypefontcache.h b/src/fontcache/truetypefontcache.h index 2ce94c5d35..7714823305 100644 --- a/src/fontcache/truetypefontcache.h +++ b/src/fontcache/truetypefontcache.h @@ -46,8 +46,6 @@ public: TrueTypeFontCache(FontSize fs, int pixels); virtual ~TrueTypeFontCache(); int GetFontSize() const override { return this->used_size; } - void SetUnicodeGlyph(char32_t key, SpriteID sprite) override { this->parent->SetUnicodeGlyph(key, sprite); } - void InitializeUnicodeGlyphMap() override { this->parent->InitializeUnicodeGlyphMap(); } const Sprite *GetGlyph(GlyphID key) override; void ClearFontCache() override; uint GetGlyphWidth(GlyphID key) override; diff --git a/src/tests/mock_fontcache.h b/src/tests/mock_fontcache.h index 5ae4103f65..c159742a31 100644 --- a/src/tests/mock_fontcache.h +++ b/src/tests/mock_fontcache.h @@ -21,8 +21,6 @@ public: this->height = FontCache::GetDefaultFontHeight(this->fs); } - void SetUnicodeGlyph(char32_t, SpriteID) override {} - void InitializeUnicodeGlyphMap() override {} void ClearFontCache() override {} const Sprite *GetGlyph(GlyphID) override { return nullptr; } uint GetGlyphWidth(GlyphID) override { return this->height / 2; }