// Given a dictionary and glyphs, encode the data for all the glyphs. #pragma once #include "datafile.hh" #include #include namespace mcufont { namespace rlefont { struct encoded_font_t { // RLE-encoded format for storing the dictionary entries. // Each item is a byte. Top bit means the value in the original bitstream, // and the bottom 7 bits store the repetition count. typedef std::vector rlestring_t; // Reference encoded format for storing the glyphs. // Each item is a reference to the dictionary. // Values 0 and 1 are hardcoded to mean 0 and 1. // All other values mean dictionary entry at (i-2). typedef std::vector refstring_t; std::vector rle_dictionary; std::vector ref_dictionary; std::vector glyphs; }; // Encode all the glyphs. std::unique_ptr encode_font(const DataFile &datafile, bool fast = true); // Sum up the total size of the encoded glyphs + dictionary. size_t get_encoded_size(const encoded_font_t &encoded); inline size_t get_encoded_size(const DataFile &datafile, bool fast = true) { std::unique_ptr e = encode_font(datafile, fast); return get_encoded_size(*e); } // Decode a single glyph (for verification). std::unique_ptr decode_glyph( const encoded_font_t &encoded, const encoded_font_t::refstring_t &refstring, const DataFile::fontinfo_t &fontinfo); // Decode a single glyph (for verification). std::unique_ptr decode_glyph( const encoded_font_t &encoded, size_t index, const DataFile::fontinfo_t &fontinfo); }} #ifdef CXXTEST_RUNNING #include using namespace mcufont; using namespace mcufont::rlefont; class RLEFontEncodeTests: public CxxTest::TestSuite { public: void testEncode() { std::istringstream s(testfile); std::unique_ptr f = DataFile::Load(s); std::unique_ptr e = encode_font(*f, false); TS_ASSERT_EQUALS(e->glyphs.size(), 3); // Expected values for dictionary encoded_font_t::rlestring_t dict0 = {0x01, 0xCE, 0x01, 0xCE}; encoded_font_t::rlestring_t dict1 = {0x0C}; encoded_font_t::rlestring_t dict2 = {0xFE}; encoded_font_t::refstring_t dict3 = {24, 24}; TS_ASSERT(e->rle_dictionary.at(0) == dict0); TS_ASSERT(e->rle_dictionary.at(1) == dict1); TS_ASSERT(e->rle_dictionary.at(2) == dict2); TS_ASSERT(e->ref_dictionary.at(0) == dict3); // Expected values for glyphs encoded_font_t::refstring_t glyph0 = {27, 27, 27}; encoded_font_t::refstring_t glyph1 = {24, 0, 132, 25, 14}; encoded_font_t::refstring_t glyph2 = {228, 26, 244, 14, 14, 14, 228, 26, 16}; TS_ASSERT_EQUALS(e->glyphs.at(0), glyph0); TS_ASSERT_EQUALS(e->glyphs.at(1), glyph1); TS_ASSERT_EQUALS(e->glyphs.at(2), glyph2); } void testDecode() { std::istringstream s(testfile); std::unique_ptr f = DataFile::Load(s); std::unique_ptr e = encode_font(*f, false); for (size_t i = 0; i < 3; i++) { std::unique_ptr dec; dec = decode_glyph(*e, i, f->GetFontInfo()); TS_ASSERT_EQUALS(*dec, f->GetGlyphEntry(i).data); } } private: static constexpr const char *testfile = "Version 1\n" "FontName Sans Serif\n" "MaxWidth 4\n" "MaxHeight 6\n" "BaselineX 1\n" "BaselineY 1\n" "DictEntry 1 0 0E0E\n" "DictEntry 1 0 000000000000\n" "DictEntry 1 0 EEEE\n" "DictEntry 1 1 0E0E0E0E\n" "Glyph 0 4 0E0E0E0E0E0E0E0E0E0E0E0E\n" "Glyph 1 4 0E0E0000000000000000000E\n" "Glyph 2 4 0000EEEE000EEE0000EEEE00\n"; }; #endif