version 2.8
encode_rlefont.hh
1 // Given a dictionary and glyphs, encode the data for all the glyphs.
2 
3 #pragma once
4 
5 #include "datafile.hh"
6 #include <vector>
7 #include <memory>
8 
9 namespace mcufont {
10 namespace rlefont {
11 
12 struct encoded_font_t
13 {
14  // RLE-encoded format for storing the dictionary entries.
15  // Each item is a byte. Top bit means the value in the original bitstream,
16  // and the bottom 7 bits store the repetition count.
17  typedef std::vector<uint8_t> rlestring_t;
18 
19  // Reference encoded format for storing the glyphs.
20  // Each item is a reference to the dictionary.
21  // Values 0 and 1 are hardcoded to mean 0 and 1.
22  // All other values mean dictionary entry at (i-2).
23  typedef std::vector<uint8_t> refstring_t;
24 
25  std::vector<rlestring_t> rle_dictionary;
26  std::vector<refstring_t> ref_dictionary;
27  std::vector<refstring_t> glyphs;
28 };
29 
30 // Encode all the glyphs.
31 std::unique_ptr<encoded_font_t> encode_font(const DataFile &datafile,
32  bool fast = true);
33 
34 // Sum up the total size of the encoded glyphs + dictionary.
35 size_t get_encoded_size(const encoded_font_t &encoded);
36 
37 inline size_t get_encoded_size(const DataFile &datafile, bool fast = true)
38 {
39  std::unique_ptr<encoded_font_t> e = encode_font(datafile, fast);
40  return get_encoded_size(*e);
41 }
42 
43 // Decode a single glyph (for verification).
44 std::unique_ptr<DataFile::pixels_t> decode_glyph(
45  const encoded_font_t &encoded,
46  const encoded_font_t::refstring_t &refstring,
47  const DataFile::fontinfo_t &fontinfo);
48 
49 // Decode a single glyph (for verification).
50 std::unique_ptr<DataFile::pixels_t> decode_glyph(
51  const encoded_font_t &encoded, size_t index,
52  const DataFile::fontinfo_t &fontinfo);
53 
54 }}
55 
56 
57 #ifdef CXXTEST_RUNNING
58 #include <cxxtest/TestSuite.h>
59 
60 using namespace mcufont;
61 using namespace mcufont::rlefont;
62 
63 class RLEFontEncodeTests: public CxxTest::TestSuite
64 {
65 public:
66  void testEncode()
67  {
68  std::istringstream s(testfile);
69  std::unique_ptr<DataFile> f = DataFile::Load(s);
70  std::unique_ptr<encoded_font_t> e = encode_font(*f, false);
71 
72  TS_ASSERT_EQUALS(e->glyphs.size(), 3);
73 
74  // Expected values for dictionary
75  encoded_font_t::rlestring_t dict0 = {0x01, 0xCE, 0x01, 0xCE};
76  encoded_font_t::rlestring_t dict1 = {0x0C};
77  encoded_font_t::rlestring_t dict2 = {0xFE};
78  encoded_font_t::refstring_t dict3 = {24, 24};
79 
80  TS_ASSERT(e->rle_dictionary.at(0) == dict0);
81  TS_ASSERT(e->rle_dictionary.at(1) == dict1);
82  TS_ASSERT(e->rle_dictionary.at(2) == dict2);
83  TS_ASSERT(e->ref_dictionary.at(0) == dict3);
84 
85  // Expected values for glyphs
86  encoded_font_t::refstring_t glyph0 = {27, 27, 27};
87  encoded_font_t::refstring_t glyph1 = {24, 0, 132, 25, 14};
88  encoded_font_t::refstring_t glyph2 = {228, 26, 244, 14, 14, 14, 228, 26, 16};
89 
90  TS_ASSERT_EQUALS(e->glyphs.at(0), glyph0);
91  TS_ASSERT_EQUALS(e->glyphs.at(1), glyph1);
92  TS_ASSERT_EQUALS(e->glyphs.at(2), glyph2);
93  }
94 
95  void testDecode()
96  {
97  std::istringstream s(testfile);
98  std::unique_ptr<DataFile> f = DataFile::Load(s);
99  std::unique_ptr<encoded_font_t> e = encode_font(*f, false);
100 
101  for (size_t i = 0; i < 3; i++)
102  {
103  std::unique_ptr<DataFile::pixels_t> dec;
104  dec = decode_glyph(*e, i, f->GetFontInfo());
105 
106  TS_ASSERT_EQUALS(*dec, f->GetGlyphEntry(i).data);
107  }
108  }
109 
110 private:
111  static constexpr const char *testfile =
112  "Version 1\n"
113  "FontName Sans Serif\n"
114  "MaxWidth 4\n"
115  "MaxHeight 6\n"
116  "BaselineX 1\n"
117  "BaselineY 1\n"
118  "DictEntry 1 0 0E0E\n"
119  "DictEntry 1 0 000000000000\n"
120  "DictEntry 1 0 EEEE\n"
121  "DictEntry 1 1 0E0E0E0E\n"
122  "Glyph 0 4 0E0E0E0E0E0E0E0E0E0E0E0E\n"
123  "Glyph 1 4 0E0E0000000000000000000E\n"
124  "Glyph 2 4 0000EEEE000EEE0000EEEE00\n";
125 };
126 #endif