/* DO NOT EDIT THIS FILE */
/* This file is autogenerated by the text-database code generator */

#ifndef TOUCHGFX_FONTCACHE_HPP
#define TOUCHGFX_FONTCACHE_HPP

#include <touchgfx/Font.hpp>
#include <touchgfx/TypedText.hpp>
#include <fonts/ApplicationFontProvider.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 keepGsubOrContextTable = false);
    void setMemory(uint8_t* memory, uint32_t size);
    void initializeCachedFont(TypedText t, CachedFont* font, bool loadGsubOrContextTable = 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 + sizeof(void*);
    }

    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, bool& outOfMemory);
    uint8_t* copyGlyph(uint8_t* top, Unicode::UnicodeChar unicode, FontId font, bool& outOfMemory);

    void cacheData(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);

    uint32_t getGlyphSize(const GlyphNode* gn)
    {
        if (byteAlignRow)
        {
            // Round up line width to byte boundary and multiply by height
            return (gn->width() * bpp + 7) / 8 * gn->height();
        }
        // Calculate number of pixels and round up to byte bounday
        return (gn->width() * gn->height() * bpp + 7) / 8;
    }

    struct
    {
        uint8_t* first; // First GlyphNode, glyph in cache;
        uint8_t* last;  // Last 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;
    uint8_t bpp;
    uint8_t byteAlignRow;
    GlyphNode currentFileGlyphNode;
};
} // namespace touchgfx

#endif // TOUCHGFX_FONTCACHE_HPP