version 2.8
export_rlefont.cc
1 #include "export_rlefont.hh"
2 #include <vector>
3 #include <iomanip>
4 #include <map>
5 #include <set>
6 #include <algorithm>
7 #include <string>
8 #include <cctype>
9 #include "exporttools.hh"
10 #include "ccfixes.hh"
11 
12 #define RLEFONT_FORMAT_VERSION 4
13 
14 namespace mcufont {
15 namespace rlefont {
16 
17 // Encode the dictionary entries and the offsets to them.
18 // Generates tables dictionary_data and dictionary_offsets.
19 static void encode_dictionary(std::ostream &out,
20  const std::string &name,
21  const DataFile &datafile,
22  const encoded_font_t &encoded)
23 {
24  std::vector<unsigned> offsets;
25  std::vector<unsigned> data;
26  for (const encoded_font_t::rlestring_t &r : encoded.rle_dictionary)
27  {
28  offsets.push_back(data.size());
29  data.insert(data.end(), r.begin(), r.end());
30  }
31 
32  for (const encoded_font_t::refstring_t &r : encoded.ref_dictionary)
33  {
34  offsets.push_back(data.size());
35  data.insert(data.end(), r.begin(), r.end());
36  }
37  offsets.push_back(data.size());
38 
39  write_const_table(out, data, "uint8_t", "mf_rlefont_" + name + "_dictionary_data");
40  write_const_table(out, offsets, "uint16_t", "mf_rlefont_" + name + "_dictionary_offsets", 4);
41 }
42 
43 // Encode the data tables for a single character range.
44 // Generates tables glyph_data_i and glyph_offsets_i.
45 static void encode_character_range(std::ostream &out,
46  const std::string &name,
47  const DataFile &datafile,
48  const encoded_font_t& encoded,
49  const char_range_t& range,
50  unsigned range_index)
51 {
52  std::vector<unsigned> offsets;
53  std::vector<unsigned> data;
54  std::map<size_t, unsigned> already_encoded;
55 
56  for (int glyph_index : range.glyph_indices)
57  {
58  if (already_encoded.count(glyph_index))
59  {
60  offsets.push_back(already_encoded[glyph_index]);
61  }
62  else
63  {
64  encoded_font_t::refstring_t r;
65  int width = 0;
66 
67  if (glyph_index >= 0)
68  {
69  r = encoded.glyphs[glyph_index];
70  width = datafile.GetGlyphEntry(glyph_index).width;
71  }
72 
73  offsets.push_back(data.size());
74  already_encoded[glyph_index] = data.size();
75 
76  data.push_back(width);
77  data.insert(data.end(), r.begin(), r.end());
78  }
79  }
80 
81  write_const_table(out, data, "uint8_t", "mf_rlefont_" + name + "_glyph_data_" + std::to_string(range_index));
82  write_const_table(out, offsets, "uint16_t", "mf_rlefont_" + name + "_glyph_offsets_" + std::to_string(range_index), 4);
83 }
84 
85 void write_source(std::ostream &out, std::string name, const DataFile &datafile)
86 {
87  name = filename_to_identifier(name);
88  std::unique_ptr<encoded_font_t> encoded = encode_font(datafile, false);
89 
90  out << std::endl;
91  out << std::endl;
92  out << "/* Start of automatically generated font definition for " << name << ". */" << std::endl;
93  out << std::endl;
94 
95  out << "#ifndef MF_RLEFONT_INTERNALS" << std::endl;
96  out << "#define MF_RLEFONT_INTERNALS" << std::endl;
97  out << "#endif" << std::endl;
98  out << "#include \"mf_rlefont.h\"" << std::endl;
99  out << std::endl;
100 
101  out << "#ifndef MF_RLEFONT_VERSION_" << RLEFONT_FORMAT_VERSION << "_SUPPORTED" << std::endl;
102  out << "#error The font file is not compatible with this version of mcufont." << std::endl;
103  out << "#endif" << std::endl;
104  out << std::endl;
105 
106  // Write out the dictionary entries
107  encode_dictionary(out, name, datafile, *encoded);
108 
109  // Split the characters into ranges
110  auto get_glyph_size = [&encoded](size_t i)
111  {
112  return encoded->glyphs[i].size() + 1; // +1 byte for glyph width
113  };
114  std::vector<char_range_t> ranges = compute_char_ranges(datafile,
115  get_glyph_size, 65536, 16);
116 
117  // Write out glyph data for character ranges
118  for (size_t i = 0; i < ranges.size(); i++)
119  {
120  encode_character_range(out, name, datafile, *encoded, ranges.at(i), i);
121  }
122 
123  // Write out a table describing the character ranges
124  out << "static const struct mf_rlefont_char_range_s mf_rlefont_" << name << "_char_ranges[] = {" << std::endl;
125  for (size_t i = 0; i < ranges.size(); i++)
126  {
127  out << " {" << ranges.at(i).first_char
128  << ", " << ranges.at(i).char_count
129  << ", mf_rlefont_" << name << "_glyph_offsets_" << i
130  << ", mf_rlefont_" << name << "_glyph_data_" << i << "}," << std::endl;
131  }
132  out << "};" << std::endl;
133  out << std::endl;
134 
135  // Pull it all together in the rlefont_s structure.
136  out << "const struct mf_rlefont_s mf_rlefont_" << name << " = {" << std::endl;
137  out << " {" << std::endl;
138  out << " " << "\"" << datafile.GetFontInfo().name << "\"," << std::endl;
139  out << " " << "\"" << name << "\"," << std::endl;
140  out << " " << datafile.GetFontInfo().max_width << ", /* width */" << std::endl;
141  out << " " << datafile.GetFontInfo().max_height << ", /* height */" << std::endl;
142  out << " " << get_min_x_advance(datafile) << ", /* min x advance */" << std::endl;
143  out << " " << get_max_x_advance(datafile) << ", /* max x advance */" << std::endl;
144  out << " " << datafile.GetFontInfo().baseline_x << ", /* baseline x */" << std::endl;
145  out << " " << datafile.GetFontInfo().baseline_y << ", /* baseline y */" << std::endl;
146  out << " " << datafile.GetFontInfo().line_height << ", /* line height */" << std::endl;
147  out << " " << datafile.GetFontInfo().flags << ", /* flags */" << std::endl;
148  out << " " << select_fallback_char(datafile) << ", /* fallback character */" << std::endl;
149  out << " " << "&mf_rlefont_character_width," << std::endl;
150  out << " " << "&mf_rlefont_render_character," << std::endl;
151  out << " }," << std::endl;
152 
153  out << " " << RLEFONT_FORMAT_VERSION << ", /* version */" << std::endl;
154  out << " " << "mf_rlefont_" << name << "_dictionary_data," << std::endl;
155  out << " " << "mf_rlefont_" << name << "_dictionary_offsets," << std::endl;
156  out << " " << encoded->rle_dictionary.size() << ", /* rle dict count */" << std::endl;
157  out << " " << encoded->ref_dictionary.size() + encoded->rle_dictionary.size() << ", /* total dict count */" << std::endl;
158  out << " " << ranges.size() << ", /* char range count */" << std::endl;
159  out << " " << "mf_rlefont_" << name << "_char_ranges," << std::endl;
160  out << "};" << std::endl;
161 
162  // Write the font lookup structure
163  out << std::endl;
164  out << "#ifdef MF_INCLUDED_FONTS" << std::endl;
165  out << "/* List entry for searching fonts by name. */" << std::endl;
166  out << "static const struct mf_font_list_s mf_rlefont_" << name << "_listentry = {" << std::endl;
167  out << " MF_INCLUDED_FONTS," << std::endl;
168  out << " (struct mf_font_s*)&mf_rlefont_" << name << std::endl;
169  out << "};" << std::endl;
170  out << "#undef MF_INCLUDED_FONTS" << std::endl;
171  out << "#define MF_INCLUDED_FONTS (&mf_rlefont_" << name << "_listentry)" << std::endl;
172  out << "#endif" << std::endl;
173 
174  out << std::endl;
175  out << std::endl;
176  out << "/* End of automatically generated font definition for " << name << ". */" << std::endl;
177  out << std::endl;
178 }
179 
180 }}
181