ugfx/tools/mcufontencoder/src/encode_rlefont.hh

127 lines
3.9 KiB
C++

// Given a dictionary and glyphs, encode the data for all the glyphs.
#pragma once
#include "datafile.hh"
#include <vector>
#include <memory>
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<uint8_t> 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<uint8_t> refstring_t;
std::vector<rlestring_t> rle_dictionary;
std::vector<refstring_t> ref_dictionary;
std::vector<refstring_t> glyphs;
};
// Encode all the glyphs.
std::unique_ptr<encoded_font_t> 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<encoded_font_t> e = encode_font(datafile, fast);
return get_encoded_size(*e);
}
// Decode a single glyph (for verification).
std::unique_ptr<DataFile::pixels_t> 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<DataFile::pixels_t> decode_glyph(
const encoded_font_t &encoded, size_t index,
const DataFile::fontinfo_t &fontinfo);
}}
#ifdef CXXTEST_RUNNING
#include <cxxtest/TestSuite.h>
using namespace mcufont;
using namespace mcufont::rlefont;
class RLEFontEncodeTests: public CxxTest::TestSuite
{
public:
void testEncode()
{
std::istringstream s(testfile);
std::unique_ptr<DataFile> f = DataFile::Load(s);
std::unique_ptr<encoded_font_t> 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<DataFile> f = DataFile::Load(s);
std::unique_ptr<encoded_font_t> e = encode_font(*f, false);
for (size_t i = 0; i < 3; i++)
{
std::unique_ptr<DataFile::pixels_t> 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