Initial commit
This commit is contained in:
		| @@ -0,0 +1,28 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <fonts/ApplicationFontProvider.hpp> | ||||
| #include <fonts/GeneratedFont.hpp> | ||||
| #include <texts/TypedTextDatabase.hpp> | ||||
| <% if save_flashreader %> | ||||
|  | ||||
| touchgfx::FlashDataReader* ApplicationFontProvider::fontFlashReader = 0; | ||||
| <% end %> | ||||
|  | ||||
| touchgfx::Font* ApplicationFontProvider::getFont(touchgfx::FontId typography) | ||||
| { | ||||
| <% if typographies.empty? %> | ||||
|     return 0; | ||||
| <% else %> | ||||
|     switch (typography) | ||||
|     { | ||||
| <% typographies.each_with_index do |typography, index| %> | ||||
|     case Typography::<%= typography.name.upcase %>: | ||||
|         // <%= typography.cpp_name %>_<%= typography.font_size %>_<%= typography.bpp %>bpp | ||||
|         return const_cast<touchgfx::Font*>(TypedTextDatabase::getFonts()[<%= font_index(index) %>]); | ||||
| <% end %> | ||||
|     default: | ||||
|         return 0; | ||||
|     } | ||||
| <% end %> | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef APPLICATIONFONTPROVIDER_HPP | ||||
| #define APPLICATIONFONTPROVIDER_HPP | ||||
|  | ||||
| #include <touchgfx/FontManager.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
|     class FlashDataReader; | ||||
| } | ||||
|  | ||||
| struct Typography | ||||
| { | ||||
| <% typographies.each_with_index do |typography, index| %> | ||||
|     static const touchgfx::FontId <%= typography.name.upcase %> = <%= index %>; | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| struct TypographyFontIndex | ||||
| { | ||||
| <% typographies.each_with_index do |typography, index| %> | ||||
|     static const touchgfx::FontId <%= typography.name.upcase %> = <%= font_index(index) %>; <%= font_comment(index) %> | ||||
| <% end %> | ||||
|     static const uint16_t NUMBER_OF_FONTS = <%= max_font_index %>; | ||||
| }; | ||||
|  | ||||
| class ApplicationFontProvider : public touchgfx::FontProvider | ||||
| { | ||||
| public: | ||||
|     virtual touchgfx::Font* getFont(touchgfx::FontId typography); | ||||
|  | ||||
| <% if save_flashreader %> | ||||
|     static void setFlashReader(touchgfx::FlashDataReader* flashReader) { fontFlashReader = flashReader; } | ||||
|     static touchgfx::FlashDataReader* getFlashReader() { return fontFlashReader; } | ||||
| private: | ||||
|     static touchgfx::FlashDataReader* fontFlashReader; | ||||
| <% else %> | ||||
|     static void setFlashReader(touchgfx::FlashDataReader* /* flashReader */) { } | ||||
|     static touchgfx::FlashDataReader* getFlashReader() { return 0; } | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| #endif // APPLICATIONFONTPROVIDER_HPP | ||||
| @@ -0,0 +1,58 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <fonts/CachedFont.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| const uint8_t* CachedFont::getPixelData(const GlyphNode* glyph) const | ||||
| { | ||||
|     //if glyph is cached, then data is present just after the GlyphNode | ||||
|     if (FontCache::isCached(glyph)) | ||||
|     { | ||||
|         const uint8_t* data = FontCache::getPixelData(glyph); | ||||
|         return data; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return flashFont->getPixelData(glyph); | ||||
|     } | ||||
| } | ||||
|  | ||||
| const GlyphNode* CachedFont::getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const | ||||
| { | ||||
|     //look first in internal flash font | ||||
|     const GlyphNode* n = flashFont->find(unicode); | ||||
|  | ||||
|     if ((n == 0) && (cache != 0)) | ||||
|     { | ||||
|         //now look in FontCache table | ||||
|         n = cache->getGlyph(unicode, fontId); | ||||
|     } | ||||
|  | ||||
|     //revert to normal behaviour if still not found | ||||
|     if (n == 0 && unicode != 0 && unicode != '\n') | ||||
|     { | ||||
|         Unicode::UnicodeChar fallbackChar = flashFont->getFallbackChar(); | ||||
|         n = flashFont->find(fallbackChar); | ||||
|         if (n == 0) | ||||
|         { | ||||
|             n = cache->getGlyph(fallbackChar, fontId); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (n != 0) | ||||
|     { | ||||
|         pixelData = getPixelData(n); | ||||
|         bitsPerPixel = getBitsPerPixel(); | ||||
|         return n; | ||||
|     } | ||||
|     return (const GlyphNode*)0; | ||||
| } | ||||
|  | ||||
| int8_t CachedFont::getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const | ||||
| { | ||||
|     //Kerning is not supported by Font Caching | ||||
|     return 0; | ||||
| } | ||||
| } | ||||
| @@ -0,0 +1,71 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef CACHEDFONT_HPP | ||||
| #define CACHEDFONT_HPP | ||||
|  | ||||
| #include <fonts/GeneratedFont.hpp> | ||||
| #include <fonts/FontCache.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| class CachedFont : public GeneratedFont | ||||
| { | ||||
| public: | ||||
|     CachedFont(const struct touchgfx::BinaryFontData* data, FontId id, FontCache* _cache, const GeneratedFont* _flashFont) | ||||
|         : GeneratedFont(0, //GlyphNode* | ||||
|                         data->numberOfGlyphs, | ||||
|                         data->height, | ||||
|                         data->pixBelowBase, | ||||
|                         data->bitsPerPixel, | ||||
|                         data->byteAlignRow, | ||||
|                         data->maxLeft, | ||||
|                         data->maxRight, | ||||
|                         0, //glyphDataPointer | ||||
|                         0, //Kerning table not used for cached font | ||||
|                         data->fallbackChar, | ||||
|                         data->ellipsisChar, | ||||
|                         0), //gsubTablePointer | ||||
|           fontId(id), | ||||
|           cache(_cache), | ||||
|           flashFont(_flashFont) | ||||
|     {} | ||||
|  | ||||
|     CachedFont() : GeneratedFont() {} | ||||
|  | ||||
|     using GeneratedFont::getGlyph; | ||||
|  | ||||
|     virtual const GlyphNode* getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const; | ||||
|  | ||||
|     virtual const uint8_t* getPixelData(const GlyphNode* glyph) const; | ||||
|  | ||||
|     virtual int8_t getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const; | ||||
|  | ||||
|     void setFontCache(FontCache& cache); | ||||
|     FontId getFontId() const | ||||
|     { | ||||
|         return fontId; | ||||
|     } | ||||
|  | ||||
|     virtual const uint16_t* getGSUBTable() const | ||||
|     { | ||||
|         if (gsubTable != 0) | ||||
|         { | ||||
|             return gsubTable; | ||||
|         } | ||||
|         return flashFont->getGSUBTable(); | ||||
|     } | ||||
|  | ||||
|     virtual void setGSUBTable(const uint16_t* table) | ||||
|     { | ||||
|         gsubTable = table; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     FontId fontId; | ||||
|     FontCache* cache; | ||||
|     const GeneratedFont* flashFont; | ||||
| }; | ||||
| } // namespace touchgfx | ||||
|  | ||||
| #endif // CACHEDFONT_HPP | ||||
| @@ -0,0 +1,378 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <fonts/FontCache.hpp> | ||||
| #include <fonts/CachedFont.hpp> | ||||
| #include <texts/TypedTextDatabase.hpp> | ||||
| #include <touchgfx/TextProvider.hpp> | ||||
| #include <touchgfx/Utils.hpp> | ||||
| #include <cstring> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| FontCache::FontCache() | ||||
|     : memorySize(0), memory(0), top(0), gsubStart(0), reader(0) | ||||
| { | ||||
| } | ||||
|  | ||||
| void FontCache::clear(bool keepGsubTable /* = false */) | ||||
| { | ||||
|     memset(fontTable, 0, sizeof(fontTable)); | ||||
|  | ||||
|     //top is beginning of memory, no glyphs are cached yet | ||||
|     top = memory; | ||||
|  | ||||
|     if (!keepGsubTable) | ||||
|     { | ||||
|         //gsubStart points to end of memory (nothing loaded yet) | ||||
|         gsubStart = memory + memorySize; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void FontCache::setMemory(uint8_t* _memory, uint32_t size) | ||||
| { | ||||
|     memory = _memory; | ||||
|     memorySize = size; | ||||
|  | ||||
|     clear(); | ||||
| } | ||||
|  | ||||
| void FontCache::setReader(FontDataReader* _reader) | ||||
| { | ||||
|     reader = _reader; | ||||
| } | ||||
|  | ||||
| const GlyphNode* FontCache::getGlyph(Unicode::UnicodeChar unicode, FontId font) const | ||||
| { | ||||
|     GlyphNode* g = (GlyphNode*)fontTable[font].first; | ||||
|     while (g) | ||||
|     { | ||||
|         if (g->unicode == unicode) | ||||
|         { | ||||
|             return g; | ||||
|         } | ||||
|         GlyphNode** next = (GlyphNode**)((uint8_t*)g + SizeGlyphNode); | ||||
|         g = *next; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void FontCache::open() | ||||
| { | ||||
|     if (reader) | ||||
|     { | ||||
|         reader->open(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void FontCache::close() | ||||
| { | ||||
|     if (reader) | ||||
|     { | ||||
|         reader->close(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void FontCache::initializeCachedFont(TypedText t, CachedFont* font, bool loadGsubTable /*= false*/) | ||||
| { | ||||
|     //get font index from typed text | ||||
|     FontId fontId = t.getFontId(); | ||||
|     //reset to start of file | ||||
|     open(); | ||||
|     setPosition(0); | ||||
|  | ||||
|     assert(sizeof(touchgfx::BinaryFontData) < MAX_BUFFER_SIZE); | ||||
|     readData(buffer, sizeof(touchgfx::BinaryFontData)); | ||||
|     const struct touchgfx::BinaryFontData* binaryFontData = reinterpret_cast<const struct touchgfx::BinaryFontData*>(buffer); | ||||
|  | ||||
|     const Font** flashFonts = TypedTextDatabase::getFonts(); | ||||
|     const GeneratedFont* flashFont = static_cast<const GeneratedFont*>(flashFonts[fontId]); | ||||
|     *font = CachedFont(reinterpret_cast<const struct touchgfx::BinaryFontData*>(buffer), fontId, this, flashFont); | ||||
|  | ||||
|     if (loadGsubTable) | ||||
|     { | ||||
|         setPosition(binaryFontData->offsetToGSUB); | ||||
|  | ||||
|         const uint32_t sizeOfGSUB = binaryFontData->sizeOfFontData - binaryFontData->offsetToGSUB; | ||||
|         if (top + sizeOfGSUB < gsubStart) //room for this GSUB table | ||||
|         { | ||||
|             uint8_t* const gsubPosition = gsubStart - sizeOfGSUB; | ||||
|             readData(gsubPosition, sizeOfGSUB); | ||||
|             font->setGSUBTable(reinterpret_cast<uint16_t*>(gsubPosition)); | ||||
|             gsubStart -= sizeOfGSUB; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             font->setGSUBTable(0); | ||||
|         } | ||||
|     } | ||||
|     close(); | ||||
| } | ||||
|  | ||||
| bool FontCache::cacheString(TypedText t, const Unicode::UnicodeChar* string) | ||||
| { | ||||
|     open(); | ||||
|     if (!createSortedString(string)) | ||||
|     { | ||||
|         close(); | ||||
|         return false; | ||||
|     } | ||||
|     const bool result = cacheSortedString(t); | ||||
|     close(); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| bool FontCache::cacheLigatures(CachedFont* font, TypedText t, const Unicode::UnicodeChar* string) | ||||
| { | ||||
|     open(); | ||||
|     if (!createSortedLigatures(font, t, string, 0, 0)) | ||||
|     { | ||||
|         close(); | ||||
|         return false; | ||||
|     } | ||||
|     const bool result = cacheSortedString(t); | ||||
|     close(); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| bool FontCache::cacheSortedString(TypedText t) | ||||
| { | ||||
|     setPosition(8); //skip font index and size | ||||
|     uint32_t glyphNodeOffset; | ||||
|     uint32_t dummy; | ||||
|     readData(&glyphNodeOffset, sizeof(uint32_t)); | ||||
|     readData(&dummy, sizeof(uint32_t)); | ||||
|     readData(&glyphDataOffset, sizeof(uint32_t)); | ||||
|     readData(&dummy, sizeof(uint32_t)); | ||||
|     readData(&numGlyphs, sizeof(uint16_t)); | ||||
|  | ||||
|     FontId fontId = t.getFontId(); // Get font index from typed text | ||||
|     uint32_t bpp = t.getFont()->getBitsPerPixel(); // Get BPP from standard font | ||||
|  | ||||
|     setPosition(glyphNodeOffset); // Go to glyph nodes for font | ||||
|     currentFileGlyphNumber = 0; | ||||
|     currentFileGlyphNode.unicode = 0; // Force reading of first glyph | ||||
|  | ||||
|     const Unicode::UnicodeChar* string = sortedString; | ||||
|     Unicode::UnicodeChar last = 0; | ||||
|     GlyphNode* firstNewGlyph = 0; | ||||
|     bool outOfMemory = false; | ||||
|     while (*string) | ||||
|     { | ||||
|         Unicode::UnicodeChar ch = *string; | ||||
|         if (ch != last) | ||||
|         { | ||||
|             if (!contains(ch, fontId)) | ||||
|             { | ||||
|                 insert(ch, fontId, bpp, outOfMemory); | ||||
|                 if (outOfMemory) | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|                 if (firstNewGlyph == 0) | ||||
|                 { | ||||
|                     firstNewGlyph = (GlyphNode*)fontTable[fontId].last; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         last = ch; | ||||
|         string++; | ||||
|     } | ||||
|  | ||||
|     cacheData(bpp, firstNewGlyph); | ||||
|     return !outOfMemory; | ||||
| } | ||||
|  | ||||
| bool FontCache::contains(Unicode::UnicodeChar unicode, FontId font) const | ||||
| { | ||||
|     GlyphNode* g = (GlyphNode*)fontTable[font].first; | ||||
|     while (g) | ||||
|     { | ||||
|         if (g->unicode == unicode) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         GlyphNode** next = (GlyphNode**)((uint8_t*)g + SizeGlyphNode); | ||||
|         g = *next; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void FontCache::insert(Unicode::UnicodeChar unicode, FontId font, uint32_t bpp, bool& outOfMemory) | ||||
| { | ||||
|     //insert new glyphnode and glyph after last for font. | ||||
|     uint8_t* oldTop = top; | ||||
|     top = copyGlyph(top, unicode, font, bpp, outOfMemory); | ||||
|  | ||||
|     if (top == oldTop) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (fontTable[font].last == 0) | ||||
|     { | ||||
|         //first glyph | ||||
|         fontTable[font].first = oldTop; | ||||
|         fontTable[font].last = oldTop; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         //set next pointer of old last glyph | ||||
|         uint8_t** old_next = (uint8_t**)(fontTable[font].last + SizeGlyphNode); | ||||
|         *old_next = oldTop; | ||||
|  | ||||
|         //save new glyph as last glyph | ||||
|         fontTable[font].last = oldTop; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint8_t* FontCache::copyGlyph(uint8_t* top, Unicode::UnicodeChar unicode, FontId font, uint32_t bpp, bool& outOfMemory) | ||||
| { | ||||
|     while (currentFileGlyphNumber < numGlyphs && currentFileGlyphNode.unicode < unicode) | ||||
|     { | ||||
|         readData(¤tFileGlyphNode, sizeof(GlyphNode)); | ||||
|         currentFileGlyphNumber++; | ||||
|     } | ||||
|     if (currentFileGlyphNode.unicode != unicode) | ||||
|     { | ||||
|         //glyphnode not found | ||||
|         return top; | ||||
|     } | ||||
|  | ||||
|     //glyphnode found | ||||
|     uint32_t glyphSize = ((currentFileGlyphNode.width() + 1) & ~1) * currentFileGlyphNode.height() * bpp / 8; | ||||
|     glyphSize = (glyphSize + 3) & ~0x03; | ||||
|     uint32_t requiredMem = SizeGlyphNode + 4 + glyphSize; // GlyphNode + next ptr + glyph | ||||
|  | ||||
|     //is space available before sortedString | ||||
|     if (top + requiredMem > (uint8_t*)sortedString) | ||||
|     { | ||||
|         outOfMemory = true; | ||||
|         return top; | ||||
|     } | ||||
|  | ||||
|     *(GlyphNode*)top = currentFileGlyphNode; | ||||
|  | ||||
|     //clear next pointer | ||||
|     uint8_t** next = (uint8_t**)(top + SizeGlyphNode); | ||||
|     *next = 0; | ||||
|     top += requiredMem; | ||||
|     return top; | ||||
| } | ||||
|  | ||||
| void FontCache::cacheData(uint32_t bpp, GlyphNode* first) | ||||
| { | ||||
|     GlyphNode* gn = first; | ||||
|     while (gn) | ||||
|     { | ||||
|         uint8_t* p = (uint8_t*)gn; | ||||
|         if (gn->dataOffset != 0xFFFFFFFF) | ||||
|         { | ||||
|             p += SizeGlyphNode; | ||||
|             //next pointer | ||||
|             p += 4; | ||||
|  | ||||
|             //seek and copy | ||||
|             setPosition(glyphDataOffset + gn->dataOffset); | ||||
|             uint32_t glyphSize = ((gn->width() + 1) & ~1) * gn->height() * bpp / 8; | ||||
|             readData(p, glyphSize); | ||||
|  | ||||
|             //mark glyphNode as cached | ||||
|             gn->dataOffset = 0xFFFFFFFF; | ||||
|         } | ||||
|  | ||||
|         GlyphNode** next = (GlyphNode**)((uint8_t*)gn + SizeGlyphNode); | ||||
|         gn = *next; | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool FontCache::createSortedString(const Unicode::UnicodeChar* string) | ||||
| { | ||||
|     int length = Unicode::strlen(string); | ||||
|     //sorted string is allocated at end of buffer | ||||
|     sortedString = (Unicode::UnicodeChar*)(gsubStart - (length + 1) * 2); | ||||
|     if ((uint8_t*)sortedString < top) | ||||
|     { | ||||
|         //unable to allocate string buffer in end of memory | ||||
|         return false; | ||||
|     } | ||||
|     int n = 0; | ||||
|     Unicode::UnicodeChar* uc = sortedString; | ||||
|     while (*string) | ||||
|     { | ||||
|         *uc++ = *string++; | ||||
|         n++; | ||||
|     } | ||||
|     *uc = 0; | ||||
|     return sortSortedString(n); | ||||
| } | ||||
|  | ||||
| bool FontCache::createSortedLigatures(CachedFont* font, TypedText t, const Unicode::UnicodeChar* string, ...) | ||||
| { | ||||
|     va_list pArg; | ||||
|     va_start(pArg, string); | ||||
|     TextProvider tp; | ||||
|     tp.initialize(string, pArg, font->getGSUBTable()); | ||||
|     va_end(pArg); | ||||
|     Unicode::UnicodeChar ligature; | ||||
|     sortedString = (Unicode::UnicodeChar*)(gsubStart); | ||||
|     if ((uint8_t*)(sortedString - 1) < top) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     *--sortedString = 0; | ||||
|     int n = 0; | ||||
|     while ((ligature = tp.getNextLigature(t.getTextDirection())) != 0) | ||||
|     { | ||||
|         if ((uint8_t*)(sortedString - 1) < top) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         *--sortedString = ligature; | ||||
|         n++; | ||||
|     } | ||||
|     return sortSortedString(n); | ||||
| } | ||||
|  | ||||
| bool FontCache::sortSortedString(int n) | ||||
| { | ||||
|     Unicode::UnicodeChar* uc = sortedString; | ||||
|     for (int i = 0; i < n - 1; i++) | ||||
|     { | ||||
|         bool swapped = false; | ||||
|         for (int j = 0; j < n - i - 1; j++) | ||||
|         { | ||||
|             if (uc[j] > uc[j + 1]) | ||||
|             { | ||||
|                 Unicode::UnicodeChar temp = uc[j]; | ||||
|                 uc[j] = uc[j + 1]; | ||||
|                 uc[j + 1] = temp; | ||||
|                 swapped = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //if no two elements were swapped by inner loop, then break | ||||
|         if (!swapped) | ||||
|         { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| void FontCache::setPosition(uint32_t position) | ||||
| { | ||||
|     if (reader) | ||||
|     { | ||||
|         reader->setPosition(position); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void FontCache::readData(void* out, uint32_t numberOfBytes) | ||||
| { | ||||
|     if (reader) | ||||
|     { | ||||
|         reader->readData(out, numberOfBytes); | ||||
|     } | ||||
| } | ||||
| } // namespace touchgfx | ||||
| @@ -0,0 +1,94 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef FONTCACHE_HPP | ||||
| #define FONTCACHE_HPP | ||||
|  | ||||
| #include <fonts/ApplicationFontProvider.hpp> | ||||
| #include <touchgfx/Font.hpp> | ||||
| #include <touchgfx/TypedText.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| class CachedFont; | ||||
|  | ||||
| class FontDataReader | ||||
| { | ||||
| public: | ||||
|     virtual ~FontDataReader() { } | ||||
|     virtual void open() = 0; | ||||
|     virtual void close() = 0; | ||||
|     virtual void setPosition(uint32_t position) = 0; | ||||
|     virtual void readData(void* out, uint32_t numberOfBytes) = 0; | ||||
| }; | ||||
|  | ||||
| class FontCache | ||||
| { | ||||
| public: | ||||
|     FontCache(); | ||||
|     void setReader(FontDataReader* reader); | ||||
|     void clear(bool keepGsubTable = false); | ||||
|     void setMemory(uint8_t* memory, uint32_t size); | ||||
|     void initializeCachedFont(TypedText t, CachedFont* font, bool loadGsubTable = false); | ||||
|     bool cacheString(TypedText t, const Unicode::UnicodeChar* string); | ||||
|     bool cacheLigatures(CachedFont* font, TypedText t, const Unicode::UnicodeChar* string); | ||||
|  | ||||
|     const GlyphNode* getGlyph(Unicode::UnicodeChar unicode, FontId font) const; | ||||
|     uint32_t getMemoryUsage() | ||||
|     { | ||||
|         return memorySize - (gsubStart - top); | ||||
|     } | ||||
|  | ||||
|     void open(); | ||||
|     void close(); | ||||
|  | ||||
|     static inline const uint8_t* getPixelData(const GlyphNode* glyph) | ||||
|     { | ||||
|         return ((const uint8_t*)glyph) + SizeGlyphNode + 4; | ||||
|     } | ||||
|     static inline bool isCached(const GlyphNode* g) | ||||
|     { | ||||
|         return g->dataOffset == 0xFFFFFFFF; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     static const uint32_t SizeGlyphNode = 16; | ||||
|  | ||||
|     bool contains(Unicode::UnicodeChar unicode, FontId font) const; | ||||
|     void insert(Unicode::UnicodeChar unicode, FontId font, uint32_t bpp, bool& outOfMemory); | ||||
|     uint8_t* copyGlyph(uint8_t* top, Unicode::UnicodeChar unicode, FontId font, uint32_t bpp, bool& outOfMemory); | ||||
|  | ||||
|     void cacheData(uint32_t bpp, GlyphNode* first); | ||||
|     bool cacheSortedString(TypedText t); | ||||
|     bool createSortedString(const Unicode::UnicodeChar* string); | ||||
|     bool createSortedLigatures(CachedFont* font, TypedText t, const Unicode::UnicodeChar* string, ...); | ||||
|     bool sortSortedString(int n); | ||||
|  | ||||
|     void setPosition(uint32_t position); | ||||
|     void readData(void* out, uint32_t numberOfBytes); | ||||
|  | ||||
|     struct | ||||
|     { | ||||
|         uint8_t* first; //first glyphnode, glyph in cache; | ||||
|         uint8_t* last; //first glyphnode, glyph in cache; | ||||
|     } fontTable[MAX(TypographyFontIndex::NUMBER_OF_FONTS, 1)]; | ||||
|  | ||||
|     uint32_t memorySize; | ||||
|     uint8_t* memory;    //start of memory | ||||
|     uint8_t* top;       //first unused byte | ||||
|     uint8_t* gsubStart; //first address of GSUB tables, allocated in the end of the cache | ||||
|  | ||||
|     FontDataReader* reader; | ||||
|  | ||||
|     Unicode::UnicodeChar* sortedString; | ||||
|     //Must be bigger than BinaryFontData | ||||
|     static const uint32_t MAX_BUFFER_SIZE = 64; | ||||
|     char buffer[MAX_BUFFER_SIZE]; | ||||
|     uint32_t glyphDataOffset; | ||||
|     uint16_t numGlyphs; | ||||
|     uint16_t currentFileGlyphNumber; | ||||
|     GlyphNode currentFileGlyphNode; | ||||
| }; | ||||
| } // namespace touchgfx | ||||
|  | ||||
| #endif // FONTCACHE_HPP | ||||
| @@ -0,0 +1,43 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <fonts/GeneratedFont.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| GeneratedFont::GeneratedFont(const GlyphNode* list, uint16_t size, uint16_t height, uint8_t pixBelowBase, 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) : | ||||
|     ConstFont(list, size, height, pixBelowBase, bitsPerPixel, byteAlignRow, maxLeft, maxRight, fallbackChar, ellipsisChar), | ||||
|     glyphData(glyphDataInternalFlash), | ||||
|     kerningData(kerningList), | ||||
|     gsubTable(gsubData) | ||||
| { | ||||
| } | ||||
|  | ||||
| const uint8_t* GeneratedFont::getPixelData(const GlyphNode* glyph) const | ||||
| { | ||||
|     const uint8_t* const* table = (const uint8_t* const*)glyphData; | ||||
|     return &(table[glyph->unicode / 2048][glyph->dataOffset]); | ||||
| } | ||||
|  | ||||
| int8_t GeneratedFont::getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const | ||||
| { | ||||
|     if (!glyph || glyph->kerningTableSize == 0) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     const KerningNode* kerndata = kerningData + glyph->kerningTablePos(); | ||||
|     for (uint16_t i = glyph->kerningTableSize; i > 0; i--, kerndata++) | ||||
|     { | ||||
|         if (prevChar == kerndata->unicodePrevChar) | ||||
|         { | ||||
|             return kerndata->distance; | ||||
|         } | ||||
|         if (prevChar < kerndata->unicodePrevChar) | ||||
|         { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| } // namespace touchgfx | ||||
| @@ -0,0 +1,133 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef GENERATEDFONT_HPP | ||||
| #define GENERATEDFONT_HPP | ||||
|  | ||||
| #include <touchgfx/ConstFont.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| /** | ||||
|  * An GeneratedFont has both glyph table and glyph data placed in a flash which | ||||
|  * supports random access read (i.e. not a NAND flash) | ||||
|  * | ||||
|  * @see ConstFont | ||||
|  */ | ||||
| class GeneratedFont : public ConstFont | ||||
| { | ||||
| public: | ||||
|     /** | ||||
|      * Construct the GeneratedFont. | ||||
|      * | ||||
|      * @param list                   The array of glyphs known to this font. | ||||
|      * @param size                   The number of glyphs in list. | ||||
|      * @param height                 The height in pixels of the highest character in this font. | ||||
|      * @param pixBelowBase           The maximum number of pixels that can be drawn below the | ||||
|      *                               baseline in this font. | ||||
|      * @param bitsPerPixel           The number of bits per pixel in this font. | ||||
|      * @param byteAlignRow           Are glyphs encoded using A4 format | ||||
|      * @param maxLeft                The maximum a character extends to the left. | ||||
|      * @param maxRight               The maximum a character extends to the right. | ||||
|      * @param glyphDataInternalFlash Pointer to the glyph data for the font, placed in internal | ||||
|      *                               flash. | ||||
|      * @param kerningList            pointer to the kerning data for the font, placed in internal | ||||
|      *                               flash. | ||||
|      * @param fallbackChar           The fallback character for the typography in case no glyph is | ||||
|      *                               available. | ||||
|      * @param ellipsisChar           The ellipsis character used for truncating long texts. | ||||
|      * @param gsubTable              Pointer to GSUB table. | ||||
|      */ | ||||
|     GeneratedFont(const GlyphNode* list, uint16_t size, uint16_t height, uint8_t pixBelowBase, 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); | ||||
|  | ||||
|     using ConstFont::getGlyph; | ||||
|  | ||||
|     /** | ||||
|      * Obtains a RAM-based pointer to the pixel data for the specified glyph. | ||||
|      * | ||||
|      * @param glyph The glyph to get the pixels data of. | ||||
|      * | ||||
|      * @return The pixel data of the glyph. | ||||
|      */ | ||||
|     virtual const uint8_t* getPixelData(const GlyphNode* glyph) const; | ||||
|  | ||||
|     /** | ||||
|      * Gets the kerning distance between two characters. | ||||
|      * | ||||
|      * @param prevChar The unicode value of the previous character. | ||||
|      * @param glyph    the glyph object for the current character. | ||||
|      * | ||||
|      * @return The kerning distance between prevChar and glyph char. | ||||
|      */ | ||||
|     virtual int8_t getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const; | ||||
|  | ||||
|     /** | ||||
|      * Gets GSUB table. | ||||
|      * | ||||
|      * @return The GSUB table or null if font has GSUB no table | ||||
|      */ | ||||
|     virtual const uint16_t* getGSUBTable() const | ||||
|     { | ||||
|         return gsubTable; | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     GeneratedFont() : ConstFont(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), glyphData(0), kerningData(0), gsubTable(0) { } | ||||
|     const void* glyphData;          ///< Information describing the glyphs | ||||
|     const KerningNode* kerningData; ///< Information describing the kerning | ||||
|     const uint16_t* gsubTable;      ///< Information describing the GSUB tables | ||||
| }; | ||||
|  | ||||
| struct BinaryFontData | ||||
| { | ||||
|     uint32_t fontIndex;                // The font index (as used by TypedTextDatabase) | ||||
|     uint32_t sizeOfFontData;           // Size of the complete BinaryFont | ||||
|     uint32_t offsetToTable;            // GlyphNode[] | ||||
|     uint32_t offsetToKerning;          // KerningNode[] | ||||
|     uint32_t offsetToGlyphs;           // uint8_t[] | ||||
|     uint32_t offsetToGSUB;             // uint16_t[] | ||||
|     uint16_t numberOfGlyphs;           // Number of glyphs in Table and Glyphs | ||||
|     uint16_t height;                   // Font height from base | ||||
|     uint8_t  pixBelowBase;             // Max pixels below base | ||||
|     uint8_t  bitsPerPixel: 7;          // Bpp | ||||
|     uint8_t  byteAlignRow: 1;          // A4/A2/A1 | ||||
|     uint8_t  maxLeft;                  // The maximum a character extends to the left | ||||
|     uint8_t  maxRight;                 // The maximum a character extends to the right | ||||
|     Unicode::UnicodeChar fallbackChar; // Fallback Character for the font | ||||
|     Unicode::UnicodeChar ellipsisChar; // Ellipsis Character for the font | ||||
| }; | ||||
|  | ||||
| class BinaryFont : public GeneratedFont | ||||
| { | ||||
| public: | ||||
|     BinaryFont(const struct touchgfx::BinaryFontData* data) | ||||
|         : GeneratedFont((const GlyphNode*)((const uint8_t*)data + data->offsetToTable), | ||||
|                         data->numberOfGlyphs, | ||||
|                         data->height, | ||||
|                         data->pixBelowBase, | ||||
|                         data->bitsPerPixel, | ||||
|                         data->byteAlignRow, | ||||
|                         data->maxLeft, | ||||
|                         data->maxRight, | ||||
|                         0, | ||||
|                         (const KerningNode*)((const uint8_t*)data + data->offsetToKerning), | ||||
|                         data->fallbackChar, | ||||
|                         data->ellipsisChar, | ||||
|                         (data->offsetToGSUB == 0) ? 0 : (const uint16_t*)((const uint8_t*)data + data->offsetToGSUB)), | ||||
|           glyphData((const uint8_t*)data + data->offsetToGlyphs) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     BinaryFont() : GeneratedFont() {} | ||||
|  | ||||
|     virtual const uint8_t* getPixelData(const GlyphNode* glyph) const | ||||
|     { | ||||
|         const uint8_t* data = (const uint8_t*)glyphData; | ||||
|         return &(data[glyph->dataOffset]); | ||||
|     } | ||||
| protected: | ||||
|     const uint8_t* glyphData; | ||||
| }; | ||||
| } // namespace touchgfx | ||||
|  | ||||
| #endif // GENERATEDFONT_HPP | ||||
| @@ -0,0 +1,42 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| <% if generate_binary_files? %> | ||||
| // Empty Language file | ||||
| <% else %> | ||||
| #include <stdint.h> | ||||
| #include <touchgfx/Unicode.hpp> | ||||
|  | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const uint32_t indices<%= language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE; | ||||
| <% if not remap_strings? %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= language %>[]  TEXT_LOCATION_FLASH_ATTRIBUTE; | ||||
| <% end %> | ||||
|  | ||||
| <% if remap_strings? %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const uint32_t indices<%= language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% entries.each_with_index do |entry, index| %> | ||||
|     <%= string_index(entry) << ((index==entries.length-1) ? ' ': ',') %> // <%= entry.text_id %> | ||||
| <% end %> | ||||
| }; | ||||
| <% else %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% entries.each_with_index do |entry, index| %> | ||||
|     <%= (entry.int_array*',').to_s << ',0' << ((index==entries.length-1) ? ' ': ',') %> // <%= entry.text_id %> | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const uint32_t indices<%= language %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% index_acc = 0 %><% entries.each_with_index do |entry, index| %> | ||||
|     <%= index_acc.to_s << ((index==entries.length-1) ? ' ': ',') %> // <%= entry.text_id %><% index_acc += entry.int_array.length+1 %> | ||||
| <% end %> | ||||
| }; | ||||
| <% end %> | ||||
| <% end %> | ||||
| @@ -0,0 +1,29 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef TEXTKEYSANDLANGUAGES_HPP | ||||
| #define TEXTKEYSANDLANGUAGES_HPP | ||||
|  | ||||
| <% | ||||
| #ENUM OF LANGUAGES | ||||
| %> | ||||
| typedef enum | ||||
| { | ||||
| <% if !(countries.empty?) %> | ||||
|     <%= countries %>, | ||||
| <% end %> | ||||
|     NUMBER_OF_LANGUAGES | ||||
| } LANGUAGES; | ||||
|  | ||||
| <% | ||||
| #ENUM DEF OF TEXT_TYPES | ||||
| %> | ||||
| typedef enum | ||||
| { | ||||
| <% texts.each do |text| %> | ||||
|     <%= text.upcase %>, | ||||
| <% end %> | ||||
|     NUMBER_OF_TEXT_KEYS | ||||
| } TEXTS; | ||||
|  | ||||
| #endif // TEXTKEYSANDLANGUAGES_HPP | ||||
| @@ -0,0 +1,182 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <stdarg.h> | ||||
| #include <texts/TypedTextDatabase.hpp> | ||||
| #include <touchgfx/TextProvider.hpp> | ||||
| #include <touchgfx/Texts.hpp> | ||||
| #include <touchgfx/TypedText.hpp> | ||||
| #include <touchgfx/Unicode.hpp> | ||||
| #include <touchgfx/hal/HAL.hpp> | ||||
| #include <touchgfx/lcd/LCD.hpp> | ||||
|  | ||||
| uint16_t touchgfx::Font::getStringWidth(const touchgfx::Unicode::UnicodeChar* text, ...) const | ||||
| { | ||||
|     va_list pArg; | ||||
|     va_start(pArg, text); | ||||
|     uint16_t width = getStringWidth<%= is_rtl ? 'RTL' : 'LTR' %>(TEXT_DIRECTION_LTR, text, pArg); | ||||
|     va_end(pArg); | ||||
|     return width; | ||||
| } | ||||
|  | ||||
| uint16_t touchgfx::Font::getStringWidth(touchgfx::TextDirection textDirection, const touchgfx::Unicode::UnicodeChar* text, ...) const | ||||
| { | ||||
|     va_list pArg; | ||||
|     va_start(pArg, text); | ||||
|     uint16_t width = getStringWidth<%= is_rtl ? 'RTL' : 'LTR' %>(textDirection, text, pArg); | ||||
|     va_end(pArg); | ||||
|     return width; | ||||
| } | ||||
|  | ||||
| touchgfx::Unicode::UnicodeChar touchgfx::TextProvider::getNextLigature(TextDirection direction) | ||||
| {<% if is_rtl %> | ||||
|     nextCharacters.replaceAt0(unicodeConverter(direction));<% end %> | ||||
|     if (fontGsubTable && nextCharacters.peekChar()) | ||||
|     { | ||||
|         substituteGlyphs(); | ||||
|         if (nextCharacters.peekChar(1) == 0x093F) //Hindi I-matra | ||||
|         { | ||||
|             nextCharacters.replaceAt1(nextCharacters.peekChar()); | ||||
|             nextCharacters.replaceAt0(0x093F); | ||||
|         } | ||||
|     } | ||||
|     return getNextChar(); | ||||
| } | ||||
|  | ||||
| void touchgfx::TextProvider::initializeInternal() | ||||
| { | ||||
|     fillInputBuffer();<% if is_rtl %> | ||||
|     unicodeConverterInit();<% end %> | ||||
| } | ||||
|  | ||||
| void touchgfx::LCD::drawString(touchgfx::Rect widgetArea, const touchgfx::Rect& invalidatedArea, const touchgfx::LCD::StringVisuals& stringVisuals, const touchgfx::Unicode::UnicodeChar* format, ...) | ||||
| { | ||||
|     va_list pArg; | ||||
|     va_start(pArg, format); | ||||
|     drawString<%= is_rtl ? 'RTL' : 'LTR' %>(widgetArea, invalidatedArea, stringVisuals, format, pArg); | ||||
|     va_end(pArg); | ||||
| } | ||||
|  | ||||
| //Default typed text database | ||||
| extern const touchgfx::TypedText::TypedTextData* const typedTextDatabaseArray[]; | ||||
|  | ||||
| <% if generate_binary_files? %> | ||||
| extern const touchgfx::Unicode::UnicodeChar EmptyLanguageTexts[]; | ||||
| extern uint32_t const EmptyLanguageIndices[]; | ||||
| <% else %> | ||||
| <% if remap_strings? %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const touchgfx::Unicode::UnicodeChar texts_all_languages[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
|     <%= all_unicodes %> | ||||
| }; | ||||
| <% end %> | ||||
| <% countries.each do |lang| %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern uint32_t const indices<%= lang %>[] TEXT_LOCATION_FLASH_ATTRIBUTE; | ||||
| <% if not remap_strings? %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const touchgfx::Unicode::UnicodeChar texts<%= lang %>[] TEXT_LOCATION_FLASH_ATTRIBUTE; | ||||
| <% end %> | ||||
| <% end %> | ||||
| <% end %> | ||||
|  | ||||
| //array holding dynamically installed languages | ||||
| struct TranslationHeader | ||||
| { | ||||
|     uint32_t offset_to_texts; | ||||
|     uint32_t offset_to_indices; | ||||
|     uint32_t offset_to_typedtext; | ||||
| }; | ||||
| static const TranslationHeader* languagesArray[<%= countries.length > 0 ? countries.length : 1 %>] = { 0 }; | ||||
|  | ||||
| //Compiled and linked in languages | ||||
| static const uint32_t* const staticLanguageIndices[] = | ||||
| { | ||||
| <% if generate_binary_files? %> | ||||
|     EmptyLanguageIndices | ||||
| <% else %> | ||||
| <% if countries.empty? %> | ||||
|     0 | ||||
| <% end %> | ||||
| <% countries.each_with_index do |lang, index| %> | ||||
|     indices<%= lang %><%= (index==countries.length-1) ? '': ',' %> | ||||
| <% end %> | ||||
| <% end %> | ||||
| }; | ||||
| <% if generate_binary_files? %> | ||||
| static const touchgfx::Unicode::UnicodeChar* const staticLanguageTexts[] = { | ||||
|     EmptyLanguageTexts | ||||
| }; | ||||
| <% else %> | ||||
| <% if not remap_strings? %> | ||||
| static const touchgfx::Unicode::UnicodeChar* const staticLanguageTexts[] = { | ||||
| <% if countries.empty? %> | ||||
|     0 | ||||
| <% end %> | ||||
| <% countries.each_with_index do |lang, index| %> | ||||
|     texts<%= lang %><%= (index==countries.length-1) ? '': ',' %> | ||||
| <% end %> | ||||
| }; | ||||
| <% end %> | ||||
| <% end %> | ||||
|  | ||||
| touchgfx::LanguageId touchgfx::Texts::currentLanguage = static_cast<touchgfx::LanguageId>(0); | ||||
| static const touchgfx::Unicode::UnicodeChar* currentLanguagePtr = 0; | ||||
| static const uint32_t* currentLanguageIndices = 0; | ||||
|  | ||||
| void touchgfx::Texts::setLanguage(touchgfx::LanguageId id) | ||||
| { | ||||
|     const touchgfx::TypedText::TypedTextData* currentLanguageTypedText = 0; | ||||
|     if (id < <%= countries.length > 0 ? countries.length : 1 %>) | ||||
|     { | ||||
|         if (languagesArray[id] != 0) | ||||
|         { | ||||
|             //dynamic translation is added | ||||
|             const TranslationHeader* translation = languagesArray[id]; | ||||
|             currentLanguagePtr = (const touchgfx::Unicode::UnicodeChar*)(((const uint8_t*)translation) + translation->offset_to_texts); | ||||
|             currentLanguageIndices = (const uint32_t*)(((const uint8_t*)translation) + translation->offset_to_indices); | ||||
|             currentLanguageTypedText = (const touchgfx::TypedText::TypedTextData*)(((const uint8_t*)translation) + translation->offset_to_typedtext); | ||||
|         } | ||||
| <% if generate_binary_files? %> | ||||
|         else | ||||
|         { | ||||
|             //compiled and linked empty texts and indices in typedTextData | ||||
|             currentLanguagePtr = staticLanguageTexts[0]; | ||||
|             currentLanguageIndices = staticLanguageIndices[0]; | ||||
|             currentLanguageTypedText = typedTextDatabaseArray[0]; | ||||
|         } | ||||
| <% else %> | ||||
|         else | ||||
|         { | ||||
|             //compiled and linked in languages | ||||
| <% if remap_strings? %> | ||||
|             currentLanguagePtr = texts_all_languages; | ||||
|             currentLanguageIndices = staticLanguageIndices[id]; | ||||
| <% else %> | ||||
|             currentLanguagePtr = staticLanguageTexts[id]; | ||||
|             currentLanguageIndices = staticLanguageIndices[id]; | ||||
| <% end %> | ||||
|             currentLanguageTypedText = typedTextDatabaseArray[id]; | ||||
|         } | ||||
| <% end %> | ||||
|     } | ||||
|  | ||||
|     if (currentLanguageTypedText) | ||||
|     { | ||||
|         currentLanguage = id; | ||||
|         touchgfx::TypedText::registerTypedTextDatabase(currentLanguageTypedText, | ||||
|                                                        TypedTextDatabase::getFonts(), TypedTextDatabase::getInstanceSize()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void touchgfx::Texts::setTranslation(touchgfx::LanguageId id, const void* translation) | ||||
| { | ||||
|     languagesArray[id] = (const TranslationHeader*)translation; | ||||
| } | ||||
|  | ||||
| const touchgfx::Unicode::UnicodeChar* touchgfx::Texts::getText(TypedTextId id) const | ||||
| { | ||||
|     return ¤tLanguagePtr[currentLanguageIndices[id]]; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,145 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <touchgfx/TypedText.hpp> | ||||
| #include <fonts/<%= font_class_name%>.hpp> | ||||
| #include <texts/TypedTextDatabase.hpp> | ||||
|  | ||||
| <% fonts.each do |font| %> | ||||
| extern touchgfx::<%= font_class_name%>& <%= font%>(); | ||||
| <% end %> | ||||
|  | ||||
| const touchgfx::Font* touchgfx_fonts[] = | ||||
| { | ||||
| <% if fonts.empty? %> | ||||
|     0 | ||||
| <% end %> | ||||
| <%= fonts.map { |font| "    &(#{font}())" } * ",\n" | ||||
| %> | ||||
| }; | ||||
|  | ||||
| <% if generate_binary_files? %> | ||||
| extern const touchgfx::TypedText::TypedTextData typedText_database_EMPTY[]; | ||||
| <% else %> | ||||
| extern const touchgfx::TypedText::TypedTextData typedText_database_DEFAULT[]; | ||||
| <% end %> | ||||
| extern const touchgfx::TypedText::TypedTextData* const typedTextDatabaseArray[]; | ||||
|  | ||||
| <% if generate_binary_files? %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const touchgfx::Unicode::UnicodeChar EmptyLanguageTexts[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% layouts.each do |layout| %> | ||||
| <% typed_texts(layout).each_with_index do |entry, index| %> | ||||
|     <%= '0' << ((index==typed_texts(layout).length-1) ? ' ': ',') %> | ||||
| <% end %> | ||||
| <% break %> | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| KEEP extern const uint32_t EmptyLanguageIndices[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% layouts.each do |layout| %> | ||||
| <% index_acc = 0 %><% typed_texts(layout).each_with_index do |entry, index| %> | ||||
|     <%= index_acc.to_s << ((index==typed_texts(layout).length-1) ? ' ': ',') %><% index_acc += 1 %> | ||||
| <% end %> | ||||
| <% break %> | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| const touchgfx::TypedText::TypedTextData typedText_database_EMPTY[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% layouts.each do |layout| %> | ||||
| <% typed_texts(layout).each_with_index do |entry, index| %> | ||||
|     <%= ('{ 0, touchgfx::LEFT, touchgfx::TEXT_DIRECTION_LTR }').to_s << ((index==typed_texts(layout).length-1) ? ' ': ',') %> | ||||
| <% end %> | ||||
| <% break %> | ||||
| <% end %> | ||||
| }; | ||||
| <% else %> | ||||
| <% layouts.each do |layout| %> | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| const touchgfx::TypedText::TypedTextData typedText_database_<%= layout %>[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% if typed_texts(layout).empty?%> | ||||
|     { 0, touchgfx::LEFT, touchgfx::TEXT_DIRECTION_LTR } | ||||
| <% end %> | ||||
| <%= typed_texts(layout).map { |typed_text| | ||||
|      fontIdx = fontmap["getFont_#{typed_text.typography.cpp_name}_#{typed_text.typography.font_size}_#{typed_text.typography.bpp}bpp"] | ||||
|      alignment = "touchgfx::#{typed_text.alignment.upcase}" | ||||
|      direction = "touchgfx::TEXT_DIRECTION_#{typed_text.direction.upcase}" | ||||
|      "    { #{fontIdx}, #{alignment}, #{direction} }" | ||||
|    } * ",\n" | ||||
| %> | ||||
| }; | ||||
| <% end %> | ||||
| <% end %> | ||||
|  | ||||
| TEXT_LOCATION_FLASH_PRAGMA | ||||
| const touchgfx::TypedText::TypedTextData* const typedTextDatabaseArray[] TEXT_LOCATION_FLASH_ATTRIBUTE = | ||||
| { | ||||
| <% if generate_binary_files? %> | ||||
| <% text_entries.languages.each_with_index do |entry,index| %> | ||||
| <% if (index==text_entries.languages.length-1) %> | ||||
|     typedText_database_EMPTY | ||||
| <% else %> | ||||
|     typedText_database_EMPTY, | ||||
| <% end %> | ||||
| <% end %> | ||||
| <% else %> | ||||
| <% if text_entries.languages.empty? %> | ||||
|     typedText_database_DEFAULT | ||||
| <% end %> | ||||
| <%= text_entries.languages.map { |language| | ||||
|       "    typedText_database_#{layouts.find { |l| l == language } || 'DEFAULT'}" | ||||
|     } * ",\n" | ||||
| %> | ||||
| <% end %> | ||||
| }; | ||||
|  | ||||
| namespace TypedTextDatabase | ||||
| { | ||||
| const touchgfx::TypedText::TypedTextData* getInstance(touchgfx::LanguageId id) | ||||
| { | ||||
|     return typedTextDatabaseArray[id]; | ||||
| } | ||||
|  | ||||
| uint16_t getInstanceSize() | ||||
| { | ||||
| <% if generate_binary_files? %> | ||||
|     return sizeof(typedText_database_EMPTY) / sizeof(touchgfx::TypedText::TypedTextData); | ||||
| <% else %> | ||||
|     return sizeof(typedText_database_DEFAULT) / sizeof(touchgfx::TypedText::TypedTextData); | ||||
| <% end %> | ||||
| } | ||||
|  | ||||
| const touchgfx::Font** getFonts() | ||||
| { | ||||
|     return touchgfx_fonts; | ||||
| } | ||||
|  | ||||
| const touchgfx::Font* setFont(touchgfx::FontId fontId, const touchgfx::Font* font) | ||||
| { | ||||
|     const touchgfx::Font* old = touchgfx_fonts[fontId]; | ||||
|     touchgfx_fonts[fontId] = font; | ||||
|     return old; | ||||
| } | ||||
|  | ||||
| void resetFont(touchgfx::FontId fontId) | ||||
| { | ||||
| <% if fonts.empty? %> | ||||
|     return; | ||||
| <% else %> | ||||
|     switch (fontId) | ||||
|     { | ||||
| <% fonts.each_with_index do |font, index| %> | ||||
|     case <%= index %>: | ||||
|         touchgfx_fonts[<%= index %>] = &(<%= font %>()); | ||||
|         break; | ||||
| <% end %> | ||||
|     } | ||||
| <% end %> | ||||
| } | ||||
| }  // namespace TypedTextDatabase | ||||
| @@ -0,0 +1,21 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef TYPEDTEXTDATABASE_HPP | ||||
| #define TYPEDTEXTDATABASE_HPP | ||||
|  | ||||
| #include <touchgfx/hal/Types.hpp> | ||||
| #include <touchgfx/TypedText.hpp> | ||||
|  | ||||
| namespace TypedTextDatabase | ||||
| { | ||||
| class TypedTextData; | ||||
| const touchgfx::TypedText::TypedTextData* getInstance(touchgfx::LanguageId id); | ||||
| const touchgfx::TypedText::TypedTextData* getInstance(); | ||||
| const touchgfx::Font** getFonts(); | ||||
| const touchgfx::Font* setFont(touchgfx::FontId fontId, const touchgfx::Font*); | ||||
| void resetFont(touchgfx::FontId fontId); | ||||
| uint16_t getInstanceSize(); | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,148 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #include <fonts/UnmappedDataFont.hpp> | ||||
| #include <fonts/ApplicationFontProvider.hpp> | ||||
| #include <touchgfx/hal/FlashDataReader.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| GlyphNode UnmappedDataFont::glyphNodeBuffer; | ||||
|  | ||||
| UnmappedDataFont::UnmappedDataFont(const GlyphNode* list, const uint16_t* unicodeList, uint16_t size, uint16_t height, uint8_t pixBelowBase, 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) : | ||||
|     Font(height, pixBelowBase, bitsPerPixel, byteAlignRow, maxLeft, maxRight, fallbackChar, ellipsisChar), | ||||
|     glyphList(list), | ||||
|     listSize(size), | ||||
|     unicodes(unicodeList), | ||||
|     glyphDataList(glyphDataList), | ||||
|     kerningData(kerningList), | ||||
|     gsubTable(gsubData) | ||||
| { | ||||
| } | ||||
|  | ||||
| const GlyphNode* UnmappedDataFont::getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const | ||||
| { | ||||
|     int index = lookupUnicode(unicode); | ||||
|  | ||||
|     if (index != -1) | ||||
|     { | ||||
|         //Read glyphNode from unmapped flash | ||||
|         touchgfx::FlashDataReader* const flashReader = ApplicationFontProvider::getFlashReader(); | ||||
|         flashReader->copyData(glyphList + index, &glyphNodeBuffer, sizeof(GlyphNode)); | ||||
|  | ||||
|         pixelData = getPixelData(const_cast<const GlyphNode*>(&glyphNodeBuffer)); | ||||
|         bitsPerPixel = getBitsPerPixel(); | ||||
|         return &glyphNodeBuffer; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| const uint8_t* UnmappedDataFont::getPixelData(const GlyphNode* glyph) const | ||||
| { | ||||
|     const uint8_t* const* table = (const uint8_t* const*)glyphDataList; | ||||
|     return &(table[glyph->unicode / 2048][glyph->dataOffset]); | ||||
| } | ||||
|  | ||||
| int8_t UnmappedDataFont::getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const | ||||
| { | ||||
|     if (!glyph || glyph->kerningTableSize == 0) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     const KerningNode* kerndata = kerningData + glyph->kerningTablePos(); | ||||
|     for (uint16_t i = glyph->kerningTableSize; i > 0; i--, kerndata++) | ||||
|     { | ||||
|         if (prevChar == kerndata->unicodePrevChar) | ||||
|         { | ||||
|             return kerndata->distance; | ||||
|         } | ||||
|         if (prevChar < kerndata->unicodePrevChar) | ||||
|         { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int UnmappedDataFont::lookupUnicode(uint16_t unicode) const | ||||
| { | ||||
|     int32_t min = 0; | ||||
|     int32_t max = listSize - 1; | ||||
|  | ||||
|     int32_t mid = min + (unicode - unicodes[min]); // Linear up from [min].unicode | ||||
|     if (mid < min) | ||||
|     { | ||||
|         // Unicode < unicodes[min] => not found | ||||
|         return -1; | ||||
|     } | ||||
|     if (mid > max) | ||||
|     { | ||||
|         // Linear up ends too high | ||||
|         mid = max - (unicodes[max] - unicode); // Linear down from [max].unicode | ||||
|         if (mid > max) | ||||
|         { | ||||
|             // Unicode > unicodes[max] => not found | ||||
|             return -1; | ||||
|         } | ||||
|         if (mid < min) | ||||
|         { | ||||
|             // Linear down ends too low, take the middle element | ||||
|             mid = (min + max) / 2; | ||||
|         } | ||||
|     } | ||||
|     while (min <= max) | ||||
|     { | ||||
|         if (unicode == unicodes[mid]) | ||||
|         { | ||||
|             // Found at [mid] | ||||
|             return mid; | ||||
|         } | ||||
|         if (unicode < unicodes[mid]) | ||||
|         { | ||||
|             // Unicode is in lower half | ||||
|             max = mid - 1; | ||||
|             if (max < min) | ||||
|             { | ||||
|                 // Range is empty => not found | ||||
|                 break; | ||||
|             } | ||||
|             // We adjusted max, try linear down from [max].unicode | ||||
|             mid = max - (unicodes[max] - unicode); | ||||
|             if (mid > max) | ||||
|             { | ||||
|                 // Unicode > [max].unicode => not found | ||||
|                 break; | ||||
|             } | ||||
|             if (mid < min) | ||||
|             { | ||||
|                 // Linear down ends too low, take the middle element | ||||
|                 mid = (min + max) / 2; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // Unicode is in upper half | ||||
|             min = mid + 1; | ||||
|             if (min > max) | ||||
|             { | ||||
|                 // Range is empty => not found | ||||
|                 break; | ||||
|             } | ||||
|             // We adjusted min, try linear up from [min].unicode | ||||
|             mid = min + (unicode - unicodes[min]); | ||||
|             if (mid < min) | ||||
|             { | ||||
|                 // Unicode < [min].unicode => not found | ||||
|                 break; | ||||
|             } | ||||
|             if (mid > max) | ||||
|             { | ||||
|                 // Linear up ends too high, take the middle element | ||||
|                 mid = (min + max) / 2; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
| } // namespace touchgfx | ||||
| @@ -0,0 +1,109 @@ | ||||
| /* DO NOT EDIT THIS FILE */ | ||||
| /* This file is autogenerated by the text-database code generator */ | ||||
|  | ||||
| #ifndef UNMAPPEDDATAFONT_HPP | ||||
| #define UNMAPPEDDATAFONT_HPP | ||||
|  | ||||
| #include <touchgfx/Font.hpp> | ||||
|  | ||||
| namespace touchgfx | ||||
| { | ||||
| /** | ||||
|  * An UnmappedDataFont has both glyph table and glyph data placed in a | ||||
|  * flash which does not support random access read (indirect | ||||
|  * access). A unicode table is located in a flash with random read | ||||
|  * access (direct access). | ||||
|  * | ||||
|  * @see Font, ConstFont | ||||
|  */ | ||||
| class UnmappedDataFont : public Font | ||||
| { | ||||
| public: | ||||
|     /** | ||||
|      * Construct the UnmappedDataFont. | ||||
|      * | ||||
|      * @param list                   The array of glyphs known to this font (indirect). | ||||
|      * @param unicodes               The array of unicodes known to this font (direct). | ||||
|      * @param size                   The number of glyphs in list. | ||||
|      * @param height                 The height in pixels of the highest character in this font. | ||||
|      * @param pixBelowBase           The maximum number of pixels that can be drawn below the | ||||
|      *                               baseline in this font. | ||||
|      * @param bitsPerPixel           The number of bits per pixel in this font. | ||||
|      * @param byteAlignRow           Are glyphs encoded using A4 format | ||||
|      * @param maxLeft                The maximum a character extends to the left. | ||||
|      * @param maxRight               The maximum a character extends to the right. | ||||
|      * @param glyphDataList          Pointer to pointers the glyph data for the font (indirect). | ||||
|      * @param kerningList            pointer to the kerning data for the font (direct). | ||||
|      * @param fallbackChar           The fallback character for the typography in case no glyph is | ||||
|      *                               available. | ||||
|      * @param ellipsisChar           The ellipsis character used for truncating long texts. | ||||
|      * @param gsubTable              Pointer to GSUB table (direct). | ||||
|      */ | ||||
|     UnmappedDataFont(const GlyphNode* list, const uint16_t* unicodes, uint16_t size, uint16_t height, uint8_t pixBelowBase, 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); | ||||
|  | ||||
|     using Font::getGlyph; | ||||
|  | ||||
|     /** | ||||
|      * Gets the glyph data associated with the specified Unicode. The | ||||
|        GlyphNode is allocated in the buffer passed to the constructor. | ||||
|      * | ||||
|      * Please note that in case of Thai letters and Arabic letters | ||||
|      * where diacritics can be placed relative to the previous | ||||
|      * character(s), please use TextProvider::getNextLigature() | ||||
|      * instead as it will create a temporary GlyphNode that will be | ||||
|      * adjusted with respect to X/Y position. | ||||
|      * | ||||
|      * @param       unicode      The character to look up. | ||||
|      * @param       pixelData    Pointer to the pixel data for the glyph if the glyph is | ||||
|      *                           found. This is set by this method. | ||||
|      * @param [out] bitsPerPixel Reference where to place the number of bits per pixel. | ||||
|      * | ||||
|      * @return A pointer to the glyph node or null if the glyph was not found. | ||||
|      */ | ||||
|     virtual const GlyphNode* getGlyph(Unicode::UnicodeChar unicode, const uint8_t*& pixelData, uint8_t& bitsPerPixel) const; | ||||
|  | ||||
|     /** | ||||
|      * Obtains the address to the pixel data for the specified glyph. | ||||
|      * | ||||
|      * @param glyph The glyph to get the pixels data of. | ||||
|      * | ||||
|      * @return The address of the pixel data of the glyph. | ||||
|      */ | ||||
|     virtual const uint8_t* getPixelData(const GlyphNode* glyph) const; | ||||
|  | ||||
|     /** | ||||
|      * Gets the kerning distance between two characters. | ||||
|      * | ||||
|      * @param prevChar The unicode value of the previous character. | ||||
|      * @param glyph    the glyph object for the current character. | ||||
|      * | ||||
|      * @return The kerning distance between prevChar and glyph char. | ||||
|      */ | ||||
|     virtual int8_t getKerning(Unicode::UnicodeChar prevChar, const GlyphNode* glyph) const; | ||||
|  | ||||
|     /** | ||||
|      * Gets GSUB table. | ||||
|      * | ||||
|      * @return The GSUB table or null if font has GSUB no table | ||||
|      */ | ||||
|     virtual const uint16_t* getGSUBTable() const | ||||
|     { | ||||
|         return gsubTable; | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     UnmappedDataFont() : Font(0, 0, 0, 0, 0, 0, 0, 0), glyphList(0), unicodes(0), glyphDataList(0), kerningData(0), gsubTable(0) { } | ||||
|     int lookupUnicode(uint16_t unicode) const; | ||||
|  | ||||
|     const GlyphNode* glyphList;     ///< The list of glyphs | ||||
|     uint16_t listSize;              ///< The size of the list of glyphs | ||||
|     const uint16_t* unicodes;       ///< LookupTable with all unicodes in this font | ||||
|     const void* glyphDataList;      ///< Information describing the glyphs (list of pointers) | ||||
|     const KerningNode* kerningData; ///< Information describing the kerning | ||||
|     const uint16_t* gsubTable;      ///< Information describing the GSUB tables | ||||
|  | ||||
|     static GlyphNode glyphNodeBuffer; ///< Buffer for GlyphNodes read from unmapped flash | ||||
| }; | ||||
| } // namespace touchgfx | ||||
|  | ||||
| #endif // UNMAPPEDDATAFONT_HPP | ||||
		Reference in New Issue
	
	Block a user