123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- // Purpose:
- // - Manage and cache glyphs, retrieving them from the renderer as needed
- #if !defined(USE_NULLFONT_ALWAYS)
- #include <AtomLyIntegration/AtomFont/GlyphCache.h>
- #include <AtomLyIntegration/AtomFont/FontTexture.h>
- //-------------------------------------------------------------------------------------------------
- AZ::GlyphCache::GlyphCache()
- : m_usage(1)
- , m_glyphBitmapWidth(0)
- , m_glyphBitmapHeight(0)
- , m_scaleBitmap(0)
- {
- m_cacheTable.clear();
- m_slotList.clear();
- }
- //-------------------------------------------------------------------------------------------------
- AZ::GlyphCache::~GlyphCache()
- {
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::Create(int iCacheSize, int glyphBitmapWidth, int glyphBitmapHeight, AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount, float sizeRatio)
- {
- m_smoothMethod = smoothMethod;
- m_smoothAmount = smoothAmount;
- m_glyphBitmapWidth = glyphBitmapWidth;
- m_glyphBitmapHeight = glyphBitmapHeight;
- if (!CreateSlotList(iCacheSize))
- {
- ReleaseSlotList();
- return 0;
- }
- int iScaledGlyphWidth = 0;
- int iScaledGlyphHeight = 0;
- switch (m_smoothMethod)
- {
- case AZ::FontSmoothMethod::SuperSample:
- {
- switch (m_smoothAmount)
- {
- case AZ::FontSmoothAmount::x2:
- iScaledGlyphWidth = m_glyphBitmapWidth << 1;
- iScaledGlyphHeight = m_glyphBitmapHeight << 1;
- break;
- case AZ::FontSmoothAmount::x4:
- iScaledGlyphWidth = m_glyphBitmapWidth << 2;
- iScaledGlyphHeight = m_glyphBitmapHeight << 2;
- break;
- }
- }
- break;
- }
- if (iScaledGlyphWidth)
- {
- m_scaleBitmap = new GlyphBitmap;
- if (!m_scaleBitmap)
- {
- Release();
- return 0;
- }
- if (!m_scaleBitmap->Create(iScaledGlyphWidth, iScaledGlyphHeight))
- {
- Release();
- return 0;
- }
- m_fontRenderer.SetGlyphBitmapSize(iScaledGlyphWidth, iScaledGlyphHeight, sizeRatio);
- }
- else
- {
- m_fontRenderer.SetGlyphBitmapSize(m_glyphBitmapWidth, m_glyphBitmapHeight, sizeRatio);
- }
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::Release()
- {
- ReleaseSlotList();
- m_cacheTable.clear();
- if (m_scaleBitmap)
- {
- m_scaleBitmap->Release();
- delete m_scaleBitmap;
- m_scaleBitmap = 0;
- }
- m_glyphBitmapWidth = 0;
- m_glyphBitmapHeight = 0;
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::LoadFontFromFile(const AZStd::string & fileName)
- {
- return m_fontRenderer.LoadFromFile(fileName);
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::LoadFontFromMemory(unsigned char* fileBuffer, int dataSize)
- {
- return m_fontRenderer.LoadFromMemory(fileBuffer, dataSize);
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::ReleaseFont()
- {
- m_fontRenderer.Release();
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::GetGlyphBitmapSize(int* width, int* height)
- {
- if (width)
- {
- *width = m_glyphBitmapWidth;
- }
- if (height)
- {
- *height = m_glyphBitmapHeight;
- }
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- void AZ::GlyphCache::SetGlyphBitmapSize(int width, int height, float sizeRatio)
- {
- m_fontRenderer.SetGlyphBitmapSize(width, height, sizeRatio);
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::PreCacheGlyph(uint32_t character, const AtomFont::GlyphSize& glyphSize, const FFont::FontHintParams& fontHintParams)
- {
- CacheTable::iterator pItor = m_cacheTable.find(GetCacheSlotKey(character, glyphSize));
- if (pItor != m_cacheTable.end())
- {
- pItor->second->m_usage = m_usage;
- return 1;
- }
- CacheSlot* slot = GetLRUSlot();
- if (!slot)
- {
- return 0;
- }
- if (slot->m_usage > 0)
- {
- UnCacheGlyph(slot->m_currentCharacter, slot->m_glyphSize);
- }
- if (m_scaleBitmap)
- {
- int iOffsetMult = 1;
- switch (m_smoothAmount)
- {
- case AZ::FontSmoothAmount::x2:
- iOffsetMult = 2;
- break;
- case AZ::FontSmoothAmount::x4:
- iOffsetMult = 4;
- break;
- }
- m_scaleBitmap->Clear();
- if (!m_fontRenderer.GetGlyph(m_scaleBitmap, &slot->m_horizontalAdvance, &slot->m_characterWidth, &slot->m_characterHeight, slot->m_characterOffsetX, slot->m_characterOffsetY, 0, 0, character, fontHintParams))
- {
- return 0;
- }
- slot->m_characterWidth >>= iOffsetMult >> 1;
- slot->m_characterHeight >>= iOffsetMult >> 1;
- m_scaleBitmap->BlitScaledTo8(slot->m_glyphBitmap.GetBuffer(), 0, 0, m_scaleBitmap->GetWidth(), m_scaleBitmap->GetHeight(), 0, 0, slot->m_glyphBitmap.GetWidth(), slot->m_glyphBitmap.GetHeight(), slot->m_glyphBitmap.GetWidth());
- }
- else
- {
- if (!m_fontRenderer.GetGlyph(&slot->m_glyphBitmap, &slot->m_horizontalAdvance, &slot->m_characterWidth, &slot->m_characterHeight, slot->m_characterOffsetX, slot->m_characterOffsetY, 0, 0, character, fontHintParams))
- {
- return 0;
- }
- }
- if (m_smoothMethod == AZ::FontSmoothMethod::Blur)
- {
- slot->m_glyphBitmap.Blur(m_smoothAmount);
- }
- slot->m_usage = m_usage;
- slot->m_currentCharacter = character;
- slot->m_glyphSize = glyphSize;
- m_cacheTable.insert(AZStd::pair<CacheTableKey, CacheSlot*>(GetCacheSlotKey(character, glyphSize), slot));
- return 1;
- }
- int AZ::GlyphCache::UnCacheGlyph(uint32_t character, const AtomFont::GlyphSize& glyphSize)
- {
- CacheTable::iterator pItor = m_cacheTable.find(GetCacheSlotKey(character, glyphSize));
- if (pItor != m_cacheTable.end())
- {
- CacheSlot* slot = pItor->second;
- slot->Reset();
- m_cacheTable.erase(pItor);
- return 1;
- }
- return 0;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::GlyphCached(uint32_t character, const AtomFont::GlyphSize& glyphSize)
- {
- return (m_cacheTable.find(GetCacheSlotKey(character, glyphSize)) != m_cacheTable.end());
- }
- //-------------------------------------------------------------------------------------------------
- AZ::CacheSlot* AZ::GlyphCache::GetLRUSlot()
- {
- unsigned int dwMinUsage = 0xffffffff;
- CacheSlot* pLRUSlot = 0;
- CacheSlot* slot;
- CacheSlotListItor pItor = m_slotList.begin();
- while (pItor != m_slotList.end())
- {
- slot = *pItor;
- if (slot->m_usage == 0)
- {
- return slot;
- }
- else
- {
- if (slot->m_usage < dwMinUsage)
- {
- pLRUSlot = slot;
- dwMinUsage = slot->m_usage;
- }
- }
- pItor++;
- }
- return pLRUSlot;
- }
- //-------------------------------------------------------------------------------------------------
- AZ::CacheSlot* AZ::GlyphCache::GetMRUSlot()
- {
- unsigned int dwMaxUsage = 0;
- CacheSlot* pMRUSlot = 0;
- CacheSlot* slot;
- CacheSlotListItor pItor = m_slotList.begin();
- while (pItor != m_slotList.end())
- {
- slot = *pItor;
- if (slot->m_usage != 0)
- {
- if (slot->m_usage > dwMaxUsage)
- {
- pMRUSlot = slot;
- dwMaxUsage = slot->m_usage;
- }
- }
- pItor++;
- }
- return pMRUSlot;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::GetGlyph(AZ::GlyphBitmap** glyph, int* horizontalAdvance, int* width, int* height, int32_t& m_characterOffsetX, int32_t& m_characterOffsetY, uint32_t character, const AZ::AtomFont::GlyphSize& glyphSize, const AZ::FFont::FontHintParams& fontHintParams)
- {
- CacheTable::iterator pItor = m_cacheTable.find(GetCacheSlotKey(character, glyphSize));
- if (pItor == m_cacheTable.end())
- {
- if (!PreCacheGlyph(character, glyphSize, fontHintParams))
- {
- return 0;
- }
- }
- pItor = m_cacheTable.find(GetCacheSlotKey(character, glyphSize));
- pItor->second->m_usage = m_usage++;
- (*glyph) = &pItor->second->m_glyphBitmap;
- if (horizontalAdvance)
- {
- *horizontalAdvance = pItor->second->m_horizontalAdvance;
- }
- if (width)
- {
- *width = pItor->second->m_characterWidth;
- }
- if (height)
- {
- *height = pItor->second->m_characterHeight;
- }
- m_characterOffsetX = pItor->second->m_characterOffsetX;
- m_characterOffsetY = pItor->second->m_characterOffsetY;
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- Vec2 AZ::GlyphCache::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph)
- {
- return m_fontRenderer.GetKerning(leftGlyph, rightGlyph);
- }
- //-------------------------------------------------------------------------------------------------
- float AZ::GlyphCache::GetAscenderToHeightRatio()
- {
- return m_fontRenderer.GetAscenderToHeightRatio();
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::CreateSlotList(int listSize)
- {
- for (int i = 0; i < listSize; i++)
- {
- CacheSlot* cacheSlot = new CacheSlot;
- if (!cacheSlot)
- {
- return 0;
- }
- if (!cacheSlot->m_glyphBitmap.Create(m_glyphBitmapWidth, m_glyphBitmapHeight))
- {
- delete cacheSlot;
- return 0;
- }
- cacheSlot->Reset();
- cacheSlot->m_slotIndex = i;
- m_slotList.push_back(cacheSlot);
- }
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- int AZ::GlyphCache::ReleaseSlotList()
- {
- CacheSlotListItor pItor = m_slotList.begin();
- while (pItor != m_slotList.end())
- {
- (*pItor)->m_glyphBitmap.Release();
- delete (*pItor);
- pItor = m_slotList.erase(pItor);
- }
- return 1;
- }
- //-------------------------------------------------------------------------------------------------
- AZ::GlyphCache::CacheTableKey AZ::GlyphCache::GetCacheSlotKey(uint32_t character, const AZ::AtomFont::GlyphSize& glyphSize) const
- {
- const AZ::AtomFont::GlyphSize clampedGlyphSize = AZ::FontTexture::ClampGlyphSize(glyphSize, m_glyphBitmapWidth, m_glyphBitmapHeight);
- return CacheTableKey(clampedGlyphSize, character);
- }
- #endif // #if !defined(USE_NULLFONT_ALWAYS)
|