encounter touchgfx build problem, giving up for now
This commit is contained in:
@ -0,0 +1,183 @@
|
||||
/* 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
|
||||
@ -0,0 +1,42 @@
|
||||
/* DO NOT EDIT THIS FILE */
|
||||
/* This file is autogenerated by the text-database code generator */
|
||||
|
||||
#ifndef TOUCHGFX_COMPRESSEDFONTCACHE_HPP
|
||||
#define TOUCHGFX_COMPRESSEDFONTCACHE_HPP
|
||||
|
||||
#include <touchgfx/hal/Types.hpp>
|
||||
#include <touchgfx/Font.hpp>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
class CompressedFontCache
|
||||
{
|
||||
public:
|
||||
static void clearCache();
|
||||
static const uint8_t* hasCachedGlyph(const GlyphNode* glyphNode);
|
||||
static void unableToCache(const GlyphNode* glyphNode, int byteSize);
|
||||
static const uint8_t* cacheGlyph(const GlyphNode* glyph, const uint8_t* compressedData);
|
||||
static int usedMemory()
|
||||
{
|
||||
return pixelsTop - (uint8_t*)bitmapFontCache + glyphsAllocated * sizeof(BitmapFontCacheKey);
|
||||
}
|
||||
|
||||
static int cacheClearCounter;
|
||||
private:
|
||||
static uint8_t* decompressGlyph(uint8_t* pixelsTop, const GlyphNode* glyphNode, const uint8_t* compressedData);
|
||||
|
||||
struct BitmapFontCacheKey
|
||||
{
|
||||
const void* glyphNode;
|
||||
const uint8_t* pixels;
|
||||
};
|
||||
|
||||
static const int cacheSizeBytes = <%= get_cache_size %>;
|
||||
static const int cacheWords = (cacheSizeBytes + 3) / 4;
|
||||
static uint32_t bitmapFontCache[cacheWords];
|
||||
static uint8_t* pixelsTop;
|
||||
static int glyphsAllocated;
|
||||
};
|
||||
} // namespace touchgfx
|
||||
|
||||
#endif // TOUCHGFX_COMPRESSEDFONTCACHE_HPP
|
||||
@ -0,0 +1,263 @@
|
||||
/* DO NOT EDIT THIS FILE */
|
||||
/* This file is autogenerated by the text-database code generator */
|
||||
|
||||
#include <fonts/CompressedUnmappedFontCache.hpp>
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
#include <touchgfx/hal/Paint.hpp>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
LOCATION_PRAGMA_32("TouchGFX_CompressedUnmappedFontCache")
|
||||
uint32_t CompressedUnmappedFontCache::bitmapFontCache[cacheWords] LOCATION_ATTRIBUTE_32("TouchGFX_CompressedUnmappedFontCache");
|
||||
uint8_t* CompressedUnmappedFontCache::pixelsTop = (uint8_t*)CompressedUnmappedFontCache::bitmapFontCache;
|
||||
int CompressedUnmappedFontCache::glyphsAllocated = 0;
|
||||
int CompressedUnmappedFontCache::cacheClearCounter = 0;
|
||||
|
||||
namespace
|
||||
{
|
||||
/* Read nibbles from compressed data in unmapped flash. Must read through reader object */
|
||||
struct NibUnmapReader
|
||||
{
|
||||
NibUnmapReader(const uint8_t* srcAddress, touchgfx::FlashDataReader* reader)
|
||||
: address(srcAddress), reader(reader), byteIndex(0), low(true)
|
||||
{
|
||||
address += bufferSize;
|
||||
reader->copyData(srcAddress, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
const uint8_t* address; //next reading address
|
||||
touchgfx::FlashDataReader* reader;
|
||||
static const int bufferSize = 16;
|
||||
uint8_t buffer[bufferSize];
|
||||
uint8_t value;
|
||||
int byteIndex;
|
||||
bool low;
|
||||
uint8_t getNext()
|
||||
{
|
||||
if (low)
|
||||
{
|
||||
value = buffer[byteIndex];
|
||||
const uint8_t val = value & 0xF;
|
||||
low = false;
|
||||
return val;
|
||||
}
|
||||
const uint8_t val = value >> 4;
|
||||
low = true;
|
||||
if (byteIndex == bufferSize - 1)
|
||||
{
|
||||
reader->copyData(address, buffer, bufferSize);
|
||||
address += bufferSize;
|
||||
byteIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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* CompressedUnmappedFontCache::decompressGlyph(uint8_t* pixelsTop, const GlyphNode* glyphNode, const uint8_t* compressedData, touchgfx::FlashDataReader* flashReader)
|
||||
{
|
||||
const int byteSize = (glyphNode->width() + 1) / 2 * glyphNode->height();
|
||||
NibWriter writer(pixelsTop, byteSize);
|
||||
NibUnmapReader reader(compressedData, flashReader);
|
||||
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
|
||||
flashReader->copyData(compressedData, pixelsTop, byteSize);
|
||||
}
|
||||
|
||||
return pixelsEnd;
|
||||
}
|
||||
|
||||
void CompressedUnmappedFontCache::clearCache()
|
||||
{
|
||||
// Wait for DMA2D/GPU2D to finish drawing
|
||||
HAL::getInstance()->lockUnlockFrameBuffer();
|
||||
glyphsAllocated = 0;
|
||||
cacheClearCounter++;
|
||||
pixelsTop = (uint8_t*)bitmapFontCache;
|
||||
}
|
||||
|
||||
void CompressedUnmappedFontCache::unableToCache(const GlyphNode* glyphNode, int byteSize)
|
||||
{
|
||||
while(1);
|
||||
}
|
||||
|
||||
const GlyphNode* CompressedUnmappedFontCache::hasCachedGlyphNode(const GlyphNode* glyphNode)
|
||||
{
|
||||
const BitmapFontCacheKey* end = (const BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
||||
const BitmapFontCacheKey* first = end - glyphsAllocated;
|
||||
while (first < end)
|
||||
{
|
||||
if (first->glyphNodeSrc == glyphNode)
|
||||
{
|
||||
return &first->glyphNodeCopy;
|
||||
}
|
||||
first++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const GlyphNode* CompressedUnmappedFontCache::hasCachedGlyphData(const GlyphNode* glyphNode, const uint8_t*& pixelData)
|
||||
{
|
||||
const BitmapFontCacheKey* end = (const BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
||||
const BitmapFontCacheKey* first = end - glyphsAllocated;
|
||||
while (first < end)
|
||||
{
|
||||
if (first->glyphNodeSrc == glyphNode)
|
||||
{
|
||||
//Pixel data can be zero!
|
||||
pixelData = first->pixels;
|
||||
return &first->glyphNodeCopy;
|
||||
}
|
||||
first++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GlyphNode* CompressedUnmappedFontCache::cacheGlyphNode(const GlyphNode* glyph)
|
||||
{
|
||||
const BitmapFontCacheKey* end = (const BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
||||
if (pixelsTop + sizeof(BitmapFontCacheKey) > (const uint8_t*)&end[-glyphsAllocated])
|
||||
{
|
||||
// Unable to fit GlyphNode in data, clear cache
|
||||
clearCache();
|
||||
}
|
||||
|
||||
glyphsAllocated++;
|
||||
BitmapFontCacheKey* key = const_cast<BitmapFontCacheKey*>(end - glyphsAllocated);
|
||||
key->glyphNodeSrc = glyph;
|
||||
key->pixels = 0;
|
||||
|
||||
return &key->glyphNodeCopy;
|
||||
}
|
||||
|
||||
const uint8_t* CompressedUnmappedFontCache::cacheGlyphData(const GlyphNode* glyph, const uint8_t* compressedData, touchgfx::FlashDataReader* reader)
|
||||
{
|
||||
// Search keys for glyph
|
||||
BitmapFontCacheKey* end = (BitmapFontCacheKey*)&bitmapFontCache[cacheWords];
|
||||
BitmapFontCacheKey* it = end - glyphsAllocated;
|
||||
while (it < end)
|
||||
{
|
||||
if (it->glyphNodeSrc == glyph)
|
||||
{
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
if (it == end)
|
||||
{
|
||||
// broken invariant!
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int byteSize = (it->glyphNodeCopy.width() + 1) / 2 * it->glyphNodeCopy.height();
|
||||
// Check if pixels can fit in cache
|
||||
if (pixelsTop + byteSize > (const uint8_t*)&end[-glyphsAllocated])
|
||||
{
|
||||
// Can it fit in a clean cache?
|
||||
if (byteSize + sizeof(BitmapFontCacheKey) > cacheSizeBytes)
|
||||
{
|
||||
unableToCache(glyph, byteSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Unable to fit pixel in data, must clear cache
|
||||
|
||||
// Save address of GlyphNode in cache
|
||||
const GlyphNode* cachedGn = &it->glyphNodeCopy;
|
||||
|
||||
// Now clear (reset pointer)
|
||||
clearCache();
|
||||
|
||||
// Insert glyph node again
|
||||
glyphsAllocated++;
|
||||
it = const_cast<BitmapFontCacheKey*>(end - 1);
|
||||
it->glyphNodeSrc = glyph;
|
||||
it->pixels = 0;
|
||||
// Copy GlyphNode content from previous position in cache
|
||||
it->glyphNodeCopy = *cachedGn;
|
||||
}
|
||||
|
||||
//Now decompress data
|
||||
const uint8_t* glyphData = pixelsTop;
|
||||
pixelsTop = decompressGlyph(pixelsTop, &it->glyphNodeCopy, compressedData, reader);
|
||||
|
||||
// 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();
|
||||
|
||||
it->pixels = glyphData;
|
||||
|
||||
return glyphData;
|
||||
}
|
||||
|
||||
} // namespace touchgfx
|
||||
@ -0,0 +1,46 @@
|
||||
/* DO NOT EDIT THIS FILE */
|
||||
/* This file is autogenerated by the text-database code generator */
|
||||
|
||||
#ifndef TOUCHGFX_COMPRESSEDUNMAPPEDFONTCACHE_HPP
|
||||
#define TOUCHGFX_COMPRESSEDUNMAPPEDFONTCACHE_HPP
|
||||
|
||||
#include <touchgfx/hal/FlashDataReader.hpp>
|
||||
#include <touchgfx/hal/Types.hpp>
|
||||
#include <touchgfx/Font.hpp>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
class CompressedUnmappedFontCache
|
||||
{
|
||||
public:
|
||||
static void clearCache();
|
||||
static const GlyphNode* hasCachedGlyphNode(const GlyphNode* glyphNode);
|
||||
static const GlyphNode* hasCachedGlyphData(const GlyphNode* glyphNode, const uint8_t*& pixelData);
|
||||
static void unableToCache(const GlyphNode* glyphNode, int byteSize);
|
||||
static GlyphNode* cacheGlyphNode(const GlyphNode* glyph);
|
||||
static const uint8_t* cacheGlyphData(const GlyphNode* glyph, const uint8_t* compressedData, touchgfx::FlashDataReader* reader);
|
||||
static int usedMemory()
|
||||
{
|
||||
return pixelsTop - (uint8_t*)bitmapFontCache + glyphsAllocated * sizeof(BitmapFontCacheKey);
|
||||
}
|
||||
|
||||
static int cacheClearCounter;
|
||||
private:
|
||||
static uint8_t* decompressGlyph(uint8_t* pixelsTop, const GlyphNode* glyphNode, const uint8_t* compressedData, touchgfx::FlashDataReader* reader);
|
||||
|
||||
struct BitmapFontCacheKey
|
||||
{
|
||||
const void* glyphNodeSrc;
|
||||
GlyphNode glyphNodeCopy;
|
||||
const uint8_t* pixels;
|
||||
};
|
||||
|
||||
static const int cacheSizeBytes = <%= get_cache_size %>;
|
||||
static const int cacheWords = (cacheSizeBytes + 3) / 4;
|
||||
static uint32_t bitmapFontCache[cacheWords];
|
||||
static uint8_t* pixelsTop;
|
||||
static int glyphsAllocated;
|
||||
};
|
||||
} // namespace touchgfx
|
||||
|
||||
#endif // TOUCHGFX_COMPRESSEDUNMAPPEDFONTCACHE_HPP
|
||||
@ -2,7 +2,9 @@
|
||||
/* This file is autogenerated by the text-database code generator */
|
||||
|
||||
#include <fonts/GeneratedFont.hpp>
|
||||
#include <fonts/CompressedFontCache.hpp>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
@ -17,8 +19,14 @@ GeneratedFont::GeneratedFont(const GlyphNode* glyphs, uint16_t numGlyphs, uint16
|
||||
|
||||
const uint8_t* GeneratedFont::getPixelData(const GlyphNode* glyph) const
|
||||
{
|
||||
// Read dataOffset as 16bit, as it may be unaligned
|
||||
volatile const uint16_t* dataOffset = (const uint16_t*)((const uint8_t*)glyph + offsetof(GlyphNode, dataOffset));
|
||||
uint32_t offset = dataOffset[0];
|
||||
offset |= dataOffset[1] << 16;
|
||||
|
||||
const uint8_t* const* table = (const uint8_t* const*)glyphData;
|
||||
return &(table[glyph->unicode / 2048][glyph->dataOffset]);
|
||||
const uint8_t* pixels = table[glyph->unicode / 2048];
|
||||
return pixels + offset;
|
||||
}
|
||||
|
||||
int8_t GeneratedFont::getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const
|
||||
@ -276,4 +284,27 @@ const VectorFontNode* GeneratedVectorFont::find(Unicode::UnicodeChar unicode) co
|
||||
return (VectorFontNode*)0;
|
||||
}
|
||||
|
||||
CompressedMappedFont::CompressedMappedFont(const GlyphNode* glyphs, uint16_t numGlyphs, uint16_t height, uint16_t baseline, uint8_t pixAboveTop, uint8_t pixBelowBottom, uint8_t bitsPerPixel, uint8_t byteAlignRow, uint8_t maxLeft, uint8_t maxRight, const uint8_t* const* glyphDataInternalFlash, const KerningNode* kerningList, const Unicode::UnicodeChar fallbackChar, const Unicode::UnicodeChar ellipsisChar, const uint16_t* const gsubData, const FontContextualFormsTable* formsTable)
|
||||
: GeneratedFont(glyphs, numGlyphs, height, baseline, pixAboveTop, pixBelowBottom, bitsPerPixel, byteAlignRow, maxLeft, maxRight, glyphDataInternalFlash, kerningList, fallbackChar, ellipsisChar, gsubData, formsTable)
|
||||
{
|
||||
}
|
||||
|
||||
const GlyphNode* CompressedMappedFont::getGlyph(Unicode::UnicodeChar unicode) const
|
||||
{
|
||||
return find(unicode);
|
||||
}
|
||||
|
||||
const uint8_t* CompressedMappedFont::getPixelData(const GlyphNode* glyph) const
|
||||
{
|
||||
const uint8_t* pixelData = CompressedFontCache::hasCachedGlyph(glyph);
|
||||
if (pixelData)
|
||||
{
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
const uint8_t* const* table = (const uint8_t* const*)glyphData;
|
||||
const uint8_t* compressedData = &(table[glyph->unicode / 2048][glyph->dataOffset & 0x3FFFFFFF]);
|
||||
return CompressedFontCache::cacheGlyph(glyph, compressedData);
|
||||
}
|
||||
|
||||
} // namespace touchgfx
|
||||
|
||||
@ -210,6 +210,18 @@ private:
|
||||
arabicTable = &contextualForms;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CompressedMappedFont : public GeneratedFont
|
||||
{
|
||||
public:
|
||||
CompressedMappedFont(const GlyphNode* glyphs, uint16_t numGlyphs, uint16_t height, uint16_t baseline, uint8_t pixAboveTop, uint8_t pixBelowBottom, uint8_t bitsPerPixel, uint8_t byteAlignRow, uint8_t maxLeft, uint8_t maxRight, const uint8_t* const* glyphDataInternalFlash, const KerningNode* kerningList, const Unicode::UnicodeChar fallbackChar, const Unicode::UnicodeChar ellipsisChar, const uint16_t* const gsubData, const FontContextualFormsTable* formsTable);
|
||||
|
||||
using GeneratedFont::getGlyph;
|
||||
virtual const GlyphNode* getGlyph(Unicode::UnicodeChar unicode) const;
|
||||
virtual const uint8_t* getPixelData(const GlyphNode* glyph) const;
|
||||
};
|
||||
|
||||
} // namespace touchgfx
|
||||
|
||||
#endif // TOUCHGFX_GENERATEDFONT_HPP
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
#include <stdint.h>
|
||||
#include <touchgfx/Unicode.hpp>
|
||||
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
KEEP extern const uint32_t indices<%= get_language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE;
|
||||
<%= get_pragma %>
|
||||
KEEP extern const uint32_t indices<%= get_language %>[]<%= get_attribute%>;
|
||||
|
||||
<% if remap_global? %>
|
||||
// Remap all strings
|
||||
@ -34,8 +34,8 @@ KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= get_language %>[] TEXT
|
||||
<% end %>
|
||||
};
|
||||
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
KEEP extern const uint32_t indices<%= get_language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = {
|
||||
<%= get_pragma %>
|
||||
KEEP extern const uint32_t indices<%= get_language %>[]<%= get_attribute%> = {
|
||||
<% text_entries = get_text_entries %>
|
||||
<% if text_entries.empty? %>
|
||||
0
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
#include <touchgfx/lcd/LCD.hpp>
|
||||
#include <texts/TypedTextDatabase.hpp>
|
||||
<% if copy_translations? %>
|
||||
#include <touchgfx/hal/FlashDataReader.hpp>
|
||||
#include <fonts/ApplicationFontProvider.hpp>
|
||||
<% end %>
|
||||
|
||||
uint16_t touchgfx::Font::getStringWidth(const touchgfx::Unicode::UnicodeChar* text, ...) const
|
||||
{
|
||||
@ -84,12 +88,12 @@ KEEP extern const touchgfx::Unicode::UnicodeChar texts_all_languages[] TEXT_LOCA
|
||||
|
||||
<% end %>
|
||||
<% get_capitalized_languages.each do |lang| %>
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
KEEP extern const uint32_t indices<%= lang %>[] TEXT_LOCATION_FLASH_ATTRIBUTE;
|
||||
<%= get_pragma %>
|
||||
KEEP extern const uint32_t indices<%= lang %>[]<%= get_attribute%>;
|
||||
|
||||
<% if !remap_global? %>
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= lang %>[] TEXT_LOCATION_FLASH_ATTRIBUTE;
|
||||
<%= get_pragma %>
|
||||
KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= lang %>[]<%= get_attribute%>;
|
||||
|
||||
<% end %>
|
||||
<% end %>
|
||||
@ -134,6 +138,16 @@ static const touchgfx::Unicode::UnicodeChar* const staticLanguageTexts[] = {
|
||||
};
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if copy_translations? %>
|
||||
static const uint32_t staticLanguageSizes[] = {
|
||||
<% get_capitalized_languages.each_with_index do |lang, index| %>
|
||||
<%= language_length(index) %><%= (index == get_number_of_languages - 1) ? '': ',' %>
|
||||
<% end %>
|
||||
};
|
||||
|
||||
static const uint32_t maxStaticLanguageSize = <%= get_max_language_length %>;
|
||||
static touchgfx::Unicode::UnicodeChar translationBuffer[maxStaticLanguageSize];
|
||||
<% end %>
|
||||
|
||||
touchgfx::LanguageId touchgfx::Texts::currentLanguage = static_cast<touchgfx::LanguageId>(0);
|
||||
static const touchgfx::Unicode::UnicodeChar* currentLanguagePtr = 0;
|
||||
@ -168,7 +182,22 @@ void touchgfx::Texts::setLanguage(touchgfx::LanguageId id)
|
||||
currentLanguagePtr = texts_all_languages;
|
||||
currentLanguageIndices = staticLanguageIndices[id];
|
||||
<% else %>
|
||||
<% if not copy_translations? %>
|
||||
currentLanguagePtr = staticLanguageTexts[id];
|
||||
<% else %>
|
||||
// Read translations from unmapped flash
|
||||
#ifdef SIMULATOR
|
||||
memcpy(translationBuffer, staticLanguageTexts[id], staticLanguageSizes[id] * 2);
|
||||
#else
|
||||
touchgfx::FlashDataReader* const flashReader = ApplicationFontProvider::getFlashReader();
|
||||
if (flashReader)
|
||||
{
|
||||
flashReader->copyData(staticLanguageTexts[id], translationBuffer, staticLanguageSizes[id] * 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
currentLanguagePtr = translationBuffer;
|
||||
<% end %>
|
||||
currentLanguageIndices = staticLanguageIndices[id];
|
||||
<% end %>
|
||||
currentLanguageTypedText = typedTextDatabaseArray[id];
|
||||
|
||||
@ -60,8 +60,8 @@ const touchgfx::TypedText::TypedTextData typedText_database_EMPTY[] TEXT_LOCATIO
|
||||
};
|
||||
<% else %>
|
||||
<% get_layouts.each do |layout| %>
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
const touchgfx::TypedText::TypedTextData typedText_database_<%= layout %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = {
|
||||
<%= get_pragma %>
|
||||
const touchgfx::TypedText::TypedTextData typedText_database_<%= layout %>[]<%= get_attribute %> = {
|
||||
<% if get_typed_texts(layout).empty? %>
|
||||
{ 0, touchgfx::LEFT, touchgfx::TEXT_DIRECTION_LTR }
|
||||
<% else %>
|
||||
@ -76,8 +76,8 @@ const touchgfx::TypedText::TypedTextData typedText_database_<%= layout %>[] TEXT
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
TEXT_LOCATION_FLASH_PRAGMA
|
||||
const touchgfx::TypedText::TypedTextData* const typedTextDatabaseArray[] TEXT_LOCATION_FLASH_ATTRIBUTE = {
|
||||
<%= get_pragma %>
|
||||
const touchgfx::TypedText::TypedTextData* const typedTextDatabaseArray[]<%= get_attribute %> = {
|
||||
<% if generate_binary_files? %>
|
||||
<% get_languages.each_with_index do |entry,index| %>
|
||||
typedText_database_EMPTY<%= index == get_languages.length-1 ? '' : ',' %>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include <touchgfx/hal/FlashDataReader.hpp>
|
||||
#include <fonts/ApplicationFontProvider.hpp>
|
||||
#include <fonts/CompressedUnmappedFontCache.hpp>
|
||||
#include <fonts/UnmappedDataFont.hpp>
|
||||
|
||||
namespace touchgfx
|
||||
@ -149,4 +150,87 @@ int UnmappedDataFont::lookupUnicode(uint16_t unicode) const
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
CompressedUnmappedDataFont::CompressedUnmappedDataFont(const GlyphNode* glyphs, const uint16_t* unicodes, uint16_t numGlyphs, uint16_t height, uint16_t baseline, uint8_t pixAboveTop, uint8_t pixBelowBottom, uint8_t bitsPerPixel, uint8_t byteAlignRow, uint8_t maxLeft, uint8_t maxRight, const uint8_t* const* glyphDataList, const KerningNode* kerningList, const Unicode::UnicodeChar fallbackChar, const Unicode::UnicodeChar ellipsisChar, const uint16_t* const gsubData, const FontContextualFormsTable* formsTable)
|
||||
: UnmappedDataFont(glyphs, unicodes, numGlyphs, height, baseline, pixAboveTop, pixBelowBottom, bitsPerPixel, byteAlignRow, maxLeft, maxRight, glyphDataList, kerningList, fallbackChar, ellipsisChar, gsubData, formsTable)
|
||||
{
|
||||
}
|
||||
|
||||
const GlyphNode* CompressedUnmappedDataFont::getGlyph(Unicode::UnicodeChar unicode) const
|
||||
{
|
||||
const int index = lookupUnicode(unicode);
|
||||
if (index != -1)
|
||||
{
|
||||
const GlyphNode* glyphNode = glyphList + index;
|
||||
|
||||
// Is the GlyphNode already cached
|
||||
const GlyphNode* cachedNode = CompressedUnmappedFontCache::hasCachedGlyphNode(glyphNode);
|
||||
if (cachedNode)
|
||||
{
|
||||
return cachedNode;
|
||||
}
|
||||
|
||||
// Read glyphNode from unmapped flash
|
||||
touchgfx::FlashDataReader* const flashReader = ApplicationFontProvider::getFlashReader();
|
||||
if (flashReader)
|
||||
{
|
||||
GlyphNode* newGlyphNode = CompressedUnmappedFontCache::cacheGlyphNode(glyphNode);
|
||||
flashReader->copyData(glyphList + index, (uint8_t*)newGlyphNode, sizeof(GlyphNode));
|
||||
return newGlyphNode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const GlyphNode* CompressedUnmappedDataFont::getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const
|
||||
{
|
||||
const int index = lookupUnicode(unicode);
|
||||
if (index != -1)
|
||||
{
|
||||
const GlyphNode* glyphNode = glyphList + index;
|
||||
const uint8_t* pixels = 0;
|
||||
const GlyphNode* cachedNode = CompressedUnmappedFontCache::hasCachedGlyphData(glyphNode, pixels);
|
||||
if (pixels)
|
||||
{
|
||||
pixelData = pixels;
|
||||
bitsPerPixel = 4;
|
||||
return cachedNode;
|
||||
}
|
||||
|
||||
// Cache glyphNode if not found already
|
||||
if (cachedNode == 0)
|
||||
{
|
||||
cachedNode = getGlyph(unicode);
|
||||
}
|
||||
if (cachedNode->width() == 0)
|
||||
{
|
||||
bitsPerPixel = 4;
|
||||
pixelData = 0;
|
||||
return cachedNode;
|
||||
}
|
||||
|
||||
// Read data from unmapped flash
|
||||
touchgfx::FlashDataReader* const flashReader = ApplicationFontProvider::getFlashReader();
|
||||
if (flashReader)
|
||||
{
|
||||
const uint8_t* const* table = (const uint8_t* const*)glyphDataList;
|
||||
const uint32_t dataOffset = cachedNode->dataOffset & 0x3FFFFFFF;
|
||||
const uint8_t* compressedData = &(table[unicode / 2048][dataOffset]);
|
||||
const uint8_t* cachedData = CompressedUnmappedFontCache::cacheGlyphData(glyphNode, compressedData, flashReader);
|
||||
if (cachedData)
|
||||
{
|
||||
bitsPerPixel = 4;
|
||||
pixelData = cachedData;
|
||||
return cachedNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t* CompressedUnmappedDataFont::getPixelData(const GlyphNode* glyph) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
} // namespace touchgfx
|
||||
|
||||
@ -121,6 +121,17 @@ protected:
|
||||
|
||||
static GlyphNode glyphNodeBuffer; ///< Buffer for GlyphNodes read from unmapped flash
|
||||
};
|
||||
|
||||
class CompressedUnmappedDataFont : public UnmappedDataFont
|
||||
{
|
||||
public:
|
||||
CompressedUnmappedDataFont(const GlyphNode* glyphs, const uint16_t* unicodes, uint16_t numGlyphs, uint16_t height, uint16_t baseline, uint8_t pixAboveTop, uint8_t pixBelowBottom, uint8_t bitsPerPixel, uint8_t byteAlignRow, uint8_t maxLeft, uint8_t maxRight, const uint8_t* const* glyphDataList, const KerningNode* kerningList, const Unicode::UnicodeChar fallbackChar, const Unicode::UnicodeChar ellipsisChar, const uint16_t* const gsubData, const FontContextualFormsTable* formsTable);
|
||||
|
||||
virtual const GlyphNode* getGlyph(Unicode::UnicodeChar unicode) const;
|
||||
virtual const GlyphNode* getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const;
|
||||
virtual const uint8_t* getPixelData(const GlyphNode* glyph) const;
|
||||
};
|
||||
|
||||
} // namespace touchgfx
|
||||
|
||||
#endif // TOUCHGFX_UNMAPPEDDATAFONT_HPP
|
||||
|
||||
Reference in New Issue
Block a user