184 lines
4.8 KiB
Plaintext
184 lines
4.8 KiB
Plaintext
/* DO NOT EDIT THIS FILE */
|
|
/* This file is autogenerated by the text-database code generator */
|
|
|
|
#include <fonts/CompressedFontCache.hpp>
|
|
#include <touchgfx/hal/HAL.hpp>
|
|
#include <touchgfx/hal/Paint.hpp>
|
|
|
|
namespace touchgfx
|
|
{
|
|
LOCATION_PRAGMA_32("TouchGFX_CompressedFontCache")
|
|
uint32_t CompressedFontCache::bitmapFontCache[cacheWords] LOCATION_ATTRIBUTE_32("TouchGFX_CompressedFontCache");
|
|
uint8_t* CompressedFontCache::pixelsTop = (uint8_t*)CompressedFontCache::bitmapFontCache;
|
|
int CompressedFontCache::glyphsAllocated = 0;
|
|
int CompressedFontCache::cacheClearCounter = 0;
|
|
|
|
namespace
|
|
{
|
|
/* Read nibbles from a compressed data array */
|
|
struct NibReader
|
|
{
|
|
NibReader(const uint8_t* buffer)
|
|
: buffer(buffer), byteIndex(0), low(true)
|
|
{}
|
|
|
|
const uint8_t* buffer;
|
|
int byteIndex;
|
|
bool low;
|
|
uint8_t getNext()
|
|
{
|
|
if (low)
|
|
{
|
|
const uint8_t val = buffer[byteIndex] & 0xF;
|
|
low = false;
|
|
return val;
|
|
}
|
|
const uint8_t val = buffer[byteIndex] >> 4;
|
|
low = true;
|
|
byteIndex++;
|
|
return val;
|
|
}
|
|
};
|
|
|
|
struct NibWriter
|
|
{
|
|
NibWriter(uint8_t* buffer, int size)
|
|
: buffer(buffer), bufferEnd(buffer + size), low(true) {}
|
|
|
|
uint8_t* buffer;
|
|
uint8_t* bufferEnd;
|
|
int low;
|
|
void put(uint8_t v)
|
|
{
|
|
if (low)
|
|
{
|
|
*buffer = v;
|
|
low = false;
|
|
return;
|
|
}
|
|
*buffer |= (v << 4);
|
|
buffer++;
|
|
low = true;
|
|
}
|
|
bool eof() { return buffer >= bufferEnd; }
|
|
};
|
|
} // anonymous namespace
|
|
|
|
uint8_t* CompressedFontCache::decompressGlyph(uint8_t* pixelsTop, const GlyphNode* glyphNode, const uint8_t* compressedData)
|
|
{
|
|
const int byteSize = (glyphNode->width() + 1) / 2 * glyphNode->height();
|
|
NibWriter writer(pixelsTop, byteSize);
|
|
NibReader reader(compressedData);
|
|
uint8_t* const pixelsEnd = pixelsTop + byteSize;
|
|
const int algorithm = glyphNode->dataOffset >> 30;
|
|
if (algorithm == 1)
|
|
{
|
|
// RLE1
|
|
while (!writer.eof())
|
|
{
|
|
const uint8_t value = reader.getNext();
|
|
if (value == 0)
|
|
{
|
|
int zeroCount = reader.getNext();
|
|
while (zeroCount)
|
|
{
|
|
writer.put(0);
|
|
zeroCount--;
|
|
}
|
|
}
|
|
writer.put(value);
|
|
}
|
|
}
|
|
else if (algorithm == 2)
|
|
{
|
|
// RLE2
|
|
while (!writer.eof())
|
|
{
|
|
const uint8_t value = reader.getNext();
|
|
if (value == 0 || value == 0xF)
|
|
{
|
|
int count = reader.getNext();
|
|
while (count)
|
|
{
|
|
writer.put(value);
|
|
count--;
|
|
}
|
|
}
|
|
writer.put(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Uncompressed
|
|
while (pixelsTop < pixelsEnd)
|
|
{
|
|
*pixelsTop++ = *compressedData++;
|
|
}
|
|
}
|
|
|
|
return pixelsEnd;
|
|
}
|
|
|
|
void CompressedFontCache::clearCache()
|
|
{
|
|
// Wait for DMA2D/GPU2D to finish drawing
|
|
HAL::getInstance()->lockUnlockFrameBuffer();
|
|
glyphsAllocated = 0;
|
|
cacheClearCounter++;
|
|
pixelsTop = (uint8_t*)bitmapFontCache;
|
|
}
|
|
|
|
void CompressedFontCache::unableToCache(const GlyphNode* glyphNode, int byteSize)
|
|
{
|
|
while(1);
|
|
}
|
|
|
|
const uint8_t* CompressedFontCache::hasCachedGlyph(const GlyphNode* glyphNode)
|
|
{
|
|
const BitmapFontCacheKey* end = (const BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
|
const BitmapFontCacheKey* first = end - glyphsAllocated;
|
|
while (first < end)
|
|
{
|
|
if (first->glyphNode == glyphNode)
|
|
{
|
|
return first->pixels;
|
|
}
|
|
first++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const uint8_t* CompressedFontCache::cacheGlyph(const GlyphNode* glyph, const uint8_t* compressedData)
|
|
{
|
|
const int byteSize = (glyph->width() + 1) / 2 * glyph->height();
|
|
if (byteSize + 8 > cacheSizeBytes)
|
|
{
|
|
unableToCache(glyph, byteSize);
|
|
return 0;
|
|
}
|
|
const BitmapFontCacheKey* end = (const BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
|
if (pixelsTop + byteSize + 8 > (const uint8_t*)&end[-glyphsAllocated])
|
|
{
|
|
// Unable to fit glyph in data, clear cache
|
|
clearCache();
|
|
}
|
|
|
|
const uint8_t* glyphData = pixelsTop;
|
|
pixelsTop = decompressGlyph(pixelsTop, glyph, compressedData);
|
|
|
|
// Flush the cache lines, must be 32byte aligned
|
|
uint8_t* rowStart = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(glyphData) & ~0x1F);
|
|
int alignmentOffset = glyphData - rowStart;
|
|
paint::flushLine((uint32_t*)rowStart, byteSize + alignmentOffset);
|
|
paint::invalidateTextureCache();
|
|
|
|
glyphsAllocated++;
|
|
|
|
BitmapFontCacheKey* key = const_cast<BitmapFontCacheKey*>(end - glyphsAllocated);
|
|
key->glyphNode = glyph;
|
|
key->pixels = glyphData;
|
|
|
|
return glyphData;
|
|
}
|
|
} // namespace touchgfx
|