1
0
Fork 0

Codechange: Use std::unordered_map for storing TrueTypeFontCache's GlyphEntry.

pull/12739/head
Peter Nelson 2024-05-12 15:03:03 +01:00 committed by Peter Nelson
parent 7b717fcccb
commit 48539992e8
7 changed files with 48 additions and 69 deletions

View File

@ -273,14 +273,14 @@ const Sprite *FreeTypeFontCache::InternalGetGlyph(GlyphID key, bool aa)
} }
} }
UniquePtrSpriteAllocator allocator;
BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator);
GlyphEntry new_glyph; GlyphEntry new_glyph;
SimpleSpriteAllocator allocator; new_glyph.data = std::move(allocator.data);
new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator); new_glyph.width = slot->advance.x >> 6;
new_glyph.width = slot->advance.x >> 6;
this->SetGlyphPtr(key, &new_glyph); return this->SetGlyphPtr(key, std::move(new_glyph)).GetSprite();
return new_glyph.sprite;
} }

View File

@ -21,7 +21,7 @@
* @param fs The font size that is going to be cached. * @param fs The font size that is going to be cached.
* @param pixels The number of pixels this font should be high. * @param pixels The number of pixels this font should be high.
*/ */
TrueTypeFontCache::TrueTypeFontCache(FontSize fs, int pixels) : FontCache(fs), req_size(pixels), glyph_to_sprite(nullptr) TrueTypeFontCache::TrueTypeFontCache(FontSize fs, int pixels) : FontCache(fs), req_size(pixels)
{ {
} }
@ -39,47 +39,22 @@ TrueTypeFontCache::~TrueTypeFontCache()
*/ */
void TrueTypeFontCache::ClearFontCache() void TrueTypeFontCache::ClearFontCache()
{ {
if (this->glyph_to_sprite == nullptr) return; this->glyph_to_sprite_map.clear();
for (int i = 0; i < 256; i++) {
if (this->glyph_to_sprite[i] == nullptr) continue;
for (int j = 0; j < 256; j++) {
free(this->glyph_to_sprite[i][j].sprite);
}
free(this->glyph_to_sprite[i]);
}
free(this->glyph_to_sprite);
this->glyph_to_sprite = nullptr;
Layouter::ResetFontCache(this->fs); Layouter::ResetFontCache(this->fs);
} }
TrueTypeFontCache::GlyphEntry *TrueTypeFontCache::GetGlyphPtr(GlyphID key) TrueTypeFontCache::GlyphEntry *TrueTypeFontCache::GetGlyphPtr(GlyphID key)
{ {
if (this->glyph_to_sprite == nullptr) return nullptr; auto found = this->glyph_to_sprite_map.find(key);
if (this->glyph_to_sprite[GB(key, 8, 8)] == nullptr) return nullptr; if (found == std::end(this->glyph_to_sprite_map)) return nullptr;
return &this->glyph_to_sprite[GB(key, 8, 8)][GB(key, 0, 8)]; return &found->second;
} }
void TrueTypeFontCache::SetGlyphPtr(GlyphID key, const GlyphEntry *glyph) TrueTypeFontCache::GlyphEntry &TrueTypeFontCache::SetGlyphPtr(GlyphID key, GlyphEntry &&glyph)
{ {
if (this->glyph_to_sprite == nullptr) { this->glyph_to_sprite_map[key] = std::move(glyph);
Debug(fontcache, 3, "Allocating root glyph cache for size {}", this->fs); return this->glyph_to_sprite_map[key];
this->glyph_to_sprite = CallocT<GlyphEntry*>(256);
}
if (this->glyph_to_sprite[GB(key, 8, 8)] == nullptr) {
Debug(fontcache, 3, "Allocating glyph cache for range 0x{:02X}00, size {}", GB(key, 8, 8), this->fs);
this->glyph_to_sprite[GB(key, 8, 8)] = CallocT<GlyphEntry>(256);
}
Debug(fontcache, 4, "Set glyph for unicode character 0x{:04X}, size {}", key, this->fs);
this->glyph_to_sprite[GB(key, 8, 8)][GB(key, 0, 8)].sprite = glyph->sprite;
this->glyph_to_sprite[GB(key, 8, 8)][GB(key, 0, 8)].width = glyph->width;
} }
bool TrueTypeFontCache::GetDrawGlyphShadow() bool TrueTypeFontCache::GetDrawGlyphShadow()
@ -92,7 +67,7 @@ uint TrueTypeFontCache::GetGlyphWidth(GlyphID key)
if ((key & SPRITE_GLYPH) != 0) return this->parent->GetGlyphWidth(key); if ((key & SPRITE_GLYPH) != 0) return this->parent->GetGlyphWidth(key);
GlyphEntry *glyph = this->GetGlyphPtr(key); GlyphEntry *glyph = this->GetGlyphPtr(key);
if (glyph == nullptr || glyph->sprite == nullptr) { if (glyph == nullptr || glyph->data == nullptr) {
this->GetGlyph(key); this->GetGlyph(key);
glyph = this->GetGlyphPtr(key); glyph = this->GetGlyphPtr(key);
} }
@ -106,7 +81,7 @@ const Sprite *TrueTypeFontCache::GetGlyph(GlyphID key)
/* Check for the glyph in our cache */ /* Check for the glyph in our cache */
GlyphEntry *glyph = this->GetGlyphPtr(key); GlyphEntry *glyph = this->GetGlyphPtr(key);
if (glyph != nullptr && glyph->sprite != nullptr) return glyph->sprite; if (glyph != nullptr && glyph->data != nullptr) return glyph->GetSprite();
return this->InternalGetGlyph(key, GetFontAAState()); return this->InternalGetGlyph(key, GetFontAAState());
} }

View File

@ -29,27 +29,16 @@ protected:
/** Container for information about a glyph. */ /** Container for information about a glyph. */
struct GlyphEntry { struct GlyphEntry {
Sprite *sprite; ///< The loaded sprite. std::unique_ptr<uint8_t[]> data; ///< The loaded sprite.
uint8_t width; ///< The width of the glyph. uint8_t width = 0; ///< The width of the glyph.
Sprite *GetSprite() { return reinterpret_cast<Sprite *>(data.get()); }
}; };
/** std::unordered_map<GlyphID, GlyphEntry> glyph_to_sprite_map{};
* The glyph cache. This is structured to reduce memory consumption.
* 1) There is a 'segment' table for each font size.
* 2) Each segment table is a discrete block of characters.
* 3) Each block contains 256 (aligned) characters sequential characters.
*
* The cache is accessed in the following way:
* For character 0x0041 ('A'): glyph_to_sprite[0x00][0x41]
* For character 0x20AC (Euro): glyph_to_sprite[0x20][0xAC]
*
* Currently only 256 segments are allocated, "limiting" us to 65536 characters.
* This can be simply changed in the two functions Get & SetGlyphPtr.
*/
GlyphEntry **glyph_to_sprite;
GlyphEntry *GetGlyphPtr(GlyphID key); GlyphEntry *GetGlyphPtr(GlyphID key);
void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph); GlyphEntry &SetGlyphPtr(GlyphID key, GlyphEntry &&glyph);
virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0; virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0;

View File

@ -276,13 +276,14 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
} }
} }
GlyphEntry new_glyph; UniquePtrSpriteAllocator allocator;
SimpleSpriteAllocator allocator; BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator);
new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator);
new_glyph.width = (uint8_t)std::round(CTFontGetAdvancesForGlyphs(this->font.get(), kCTFontOrientationDefault, &glyph, nullptr, 1));
this->SetGlyphPtr(key, &new_glyph);
return new_glyph.sprite; GlyphEntry new_glyph;
new_glyph.data = std::move(allocator.data);
new_glyph.width = (uint8_t)std::round(CTFontGetAdvancesForGlyphs(this->font.get(), kCTFontOrientationDefault, &glyph, nullptr, 1));
return this->SetGlyphPtr(key, std::move(new_glyph)).GetSprite();
} }
static CTFontDescriptorRef LoadFontFromFile(const std::string &font_name) static CTFontDescriptorRef LoadFontFromFile(const std::string &font_name)

View File

@ -252,14 +252,14 @@ void Win32FontCache::ClearFontCache()
} }
} }
UniquePtrSpriteAllocator allocator;
BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator);
GlyphEntry new_glyph; GlyphEntry new_glyph;
SimpleSpriteAllocator allocator; new_glyph.data = std::move(allocator.data);
new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(spritecollection, allocator);
new_glyph.width = gm.gmCellIncX; new_glyph.width = gm.gmCellIncX;
this->SetGlyphPtr(key, &new_glyph); return this->SetGlyphPtr(key, std::move(new_glyph)).GetSprite();
return new_glyph.sprite;
} }
/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key, bool allow_fallback) /* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key, bool allow_fallback)

View File

@ -894,6 +894,12 @@ void *SimpleSpriteAllocator::AllocatePtr(size_t size)
return MallocT<uint8_t>(size); return MallocT<uint8_t>(size);
} }
void *UniquePtrSpriteAllocator::AllocatePtr(size_t size)
{
this->data = std::make_unique<uint8_t[]>(size);
return this->data.get();
}
/** /**
* Handles the case when a sprite of different type is requested than is present in the SpriteCache. * Handles the case when a sprite of different type is requested than is present in the SpriteCache.
* For SpriteType::Font sprites, it is normal. In other cases, default sprite is loaded instead. * For SpriteType::Font sprites, it is normal. In other cases, default sprite is loaded instead.

View File

@ -37,6 +37,14 @@ protected:
void *AllocatePtr(size_t size) override; void *AllocatePtr(size_t size) override;
}; };
/** SpriteAllocator that allocates memory via a unique_ptr array. */
class UniquePtrSpriteAllocator : public SpriteAllocator {
public:
std::unique_ptr<uint8_t[]> data;
protected:
void *AllocatePtr(size_t size) override;
};
void *GetRawSprite(SpriteID sprite, SpriteType type, SpriteAllocator *allocator = nullptr, SpriteEncoder *encoder = nullptr); void *GetRawSprite(SpriteID sprite, SpriteType type, SpriteAllocator *allocator = nullptr, SpriteEncoder *encoder = nullptr);
bool SpriteExists(SpriteID sprite); bool SpriteExists(SpriteID sprite);