Advertisement
dan-masek

Bitmap Font encoding prototype 2

Apr 3rd, 2018
330
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 20.97 KB | None | 0 0
  1. #include <boost/algorithm/string/classification.hpp>
  2. #include <boost/algorithm/string/split.hpp>
  3.  
  4. #include <array>
  5. #include <cstdint>
  6. #include <fstream>
  7. #include <iostream>
  8. #include <iomanip>
  9. #include <string>
  10. #include <sstream>
  11. #include <vector>
  12.  
  13.  
  14. struct glyph
  15. {
  16.     uint8_t code;
  17.     std::array<uint16_t, 16> rows;
  18. };
  19.  
  20. struct font
  21. {
  22.     std::string header;
  23.     std::vector<glyph> glyphs;
  24.  
  25.     void sort()
  26.     {
  27.         std::sort(glyphs.begin(), glyphs.end()
  28.             , [](glyph const& l, glyph const& r) -> bool {
  29.                 return l.code < r.code;
  30.             });
  31.  
  32.     }
  33. };
  34.  
  35. font load_font_txt(std::string const& file_name)
  36. {
  37.     font f;
  38.  
  39.     std::ifstream input(file_name);
  40.     getline(input, f.header);
  41.     for (std::string line; getline(input, line);) {
  42.         std::vector<std::string> parts;
  43.         boost::split(parts, line, boost::is_any_of("|"));
  44.         std::vector<std::string> rows;
  45.         boost::split(rows, parts[1], boost::is_any_of(" "));
  46.  
  47.         glyph g;
  48.         g.code = static_cast<uint8_t>(std::stoul(parts[0]));
  49.         for (uint32_t i(0); i < 16; ++i) {
  50.             g.rows[i] = static_cast<uint16_t>(std::stoul(rows[i], nullptr, 16));
  51.         }
  52.  
  53.         f.glyphs.push_back(g);
  54.     }
  55.  
  56.     return f;
  57. }
  58.  
  59. void encode_v0(font const& f, std::vector<uint8_t>& buffer)
  60. {
  61.     std::copy(f.header.begin(), f.header.end(), std::back_inserter(buffer));
  62.     buffer.push_back('\r');
  63.     buffer.push_back('\n');
  64.     for (glyph const& g : f.glyphs) {
  65.         std::ostringstream s;
  66.         s << int(g.code) << "|";
  67.         for (uint32_t i(0); i < 16; ++i) {
  68.             s << (i ? " " : "") << std::uppercase
  69.                 << std::setfill('0') << std::setw(3) << std::hex
  70.                 << g.rows[i];
  71.         }
  72.         s << "\r\n";
  73.         std::string temp(s.str());
  74.         std::copy(temp.begin(), temp.end(), std::back_inserter(buffer));
  75.     }
  76. }
  77.  
  78. void encode_header(font const& f, std::vector<uint8_t>& buffer)
  79. {
  80.     // Store header directly
  81.     std::copy(f.header.begin(), f.header.end(), std::back_inserter(buffer));
  82.     // and terminate with null
  83.     buffer.push_back(0);
  84. }
  85.  
  86.  
  87. struct simple_bitstream
  88. {
  89.     simple_bitstream(std::vector<uint8_t>& buffer)
  90.         : buf_(buffer)
  91.         , temp_(0)
  92.         , temp_size_(0)
  93.     {
  94.     }
  95.  
  96.     void write_bits(uint32_t v, uint8_t bits)
  97.     {
  98.         if (bits) {
  99.             write_bits(v >> 1, bits - 1);
  100.             write_bit(v & 1);
  101.         }        
  102.     }
  103.  
  104.     void write_bit(uint8_t v)
  105.     {
  106.         temp_ = (temp_ << 1) | (v & 1);
  107.         ++temp_size_;
  108.         if (temp_size_ == 8) {
  109.             buf_.push_back(temp_);
  110.             temp_size_ = 0;
  111.             temp_ = 0;
  112.         }
  113.     }
  114.  
  115.     void flush()
  116.     {
  117.         for (; temp_size_;) {
  118.             write_bit(0);
  119.         }
  120.     }
  121.  
  122.     std::vector<uint8_t>& buf_;
  123.     uint8_t temp_;
  124.     uint8_t temp_size_;
  125. };
  126.  
  127. void encode_v1(font const& f, std::vector<uint8_t>& buffer)
  128. {
  129.     encode_header(f, buffer);
  130.     simple_bitstream b(buffer);
  131.     for (glyph const& g : f.glyphs) {
  132.         // Code using 1 byte
  133.         b.write_bits(g.code, 8);
  134.         for (uint32_t i(0); i < 16; ++i) {
  135.             // Pixel using 2 bytes, most significant bits first, prefixed by 4 bit padding
  136.             b.write_bits(g.rows[i], 16);
  137.         }
  138.     }
  139. }
  140.  
  141. void encode_v2(font const& f, std::vector<uint8_t>& buffer)
  142. {
  143.     encode_header(f, buffer);
  144.     simple_bitstream b(buffer);
  145.     for (glyph const& g : f.glyphs) {
  146.         // Code using 1 byte
  147.         b.write_bits(g.code, 8);
  148.         for (uint32_t i(0); i < 16; i += 2) {
  149.             // 2 pixels using 3 bytes, most significant bits first
  150.             b.write_bits(g.rows[i], 12);
  151.             b.write_bits(g.rows[i + 1], 12);
  152.         }
  153.     }
  154. }
  155.  
  156. void encode_v3(font const& f, std::vector<uint8_t>& buffer)
  157. {
  158.     encode_header(f, buffer);
  159.     simple_bitstream b(buffer);
  160.     for (glyph const& g : f.glyphs) {
  161.         // Code using 1 byte
  162.         b.write_bits(g.code, 8);
  163.  
  164.         for (uint32_t i(0); i < 16; ++i) {
  165.             uint16_t row(g.rows[i]);
  166.             if (row == 0) {
  167.                 // An empty row
  168.                 b.write_bit(1);
  169.             } else {
  170.                 // Verbatim row
  171.                 b.write_bit(0);
  172.                 b.write_bits(row, 12);
  173.             }
  174.         }
  175.     }
  176. }
  177.  
  178. // Find nearest identical preceding row in this glyph
  179. uint8_t find_nearest_copy(glyph const& g, uint32_t i)
  180. {
  181.     uint8_t offset(0);
  182.     uint16_t row(g.rows[i]);
  183.     for (uint8_t j(1); j < i; ++j) {
  184.         if (row == g.rows[i - j]) {
  185.             offset = j;
  186.             break;
  187.         }
  188.     }
  189.     return offset;
  190. }
  191.  
  192. void encode_v4(font const& f, std::vector<uint8_t>& buffer)
  193. {
  194.     uint32_t OP_VERBATIM(0), OP_COPY(1);
  195.  
  196.     encode_header(f, buffer);
  197.     simple_bitstream b(buffer);
  198.     for (glyph const& g : f.glyphs) {
  199.         // Code using 1 byte
  200.         b.write_bits(g.code, 8);
  201.  
  202.         for (uint32_t i(0); i < 16; ++i) {
  203.             uint16_t row(g.rows[i]);
  204.             if (row == 0) {
  205.                 // Empty row, copy with offset 0
  206.                 b.write_bit(OP_COPY);
  207.                 b.write_bits(0, 4);
  208.                 continue;
  209.             }
  210.  
  211.             // Find nearest identical preceding row in this glyph
  212.             uint8_t offset(find_nearest_copy(g, i));
  213.             if (offset) {
  214.                 // Copy with non-zero offset
  215.                 b.write_bit(OP_COPY);
  216.                 b.write_bits(offset, 4);
  217.             } else {
  218.                 // Verbatim row
  219.                 b.write_bit(OP_VERBATIM);
  220.                 b.write_bits(row, 12);
  221.             }
  222.         }
  223.     }
  224. }
  225.  
  226. void encode_v5(font const& f, std::vector<uint8_t>& buffer)
  227. {
  228.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2);
  229.  
  230.     encode_header(f, buffer);
  231.     simple_bitstream b(buffer);
  232.     for (glyph const& g : f.glyphs) {
  233.         // Code using 1 byte
  234.         b.write_bits(g.code, 8);
  235.  
  236.         for (uint32_t i(0); i < 16; ++i) {
  237.             uint16_t row(g.rows[i]);
  238.             if (row == 0) {
  239.                 // Empty row
  240.                 b.write_bits(OP_EMPTY, 2);
  241.                 continue;
  242.             }
  243.  
  244.             // Find nearest identical preceding row in this glyph
  245.             uint8_t offset(find_nearest_copy(g, i));
  246.             if (offset) {
  247.                 // Copy with non-zero offset
  248.                 b.write_bits(OP_COPY, 2);
  249.                 b.write_bits(offset, 4);
  250.             } else {
  251.                 // Verbatim row
  252.                 b.write_bits(OP_VERBATIM, 2);
  253.                 b.write_bits(row, 12);
  254.             }
  255.         }
  256.     }
  257. }
  258.  
  259. uint32_t find_end_row(glyph const& g)
  260. {
  261.     uint32_t end_row(16);
  262.     for (uint32_t i(0); i < 16; ++i) {
  263.         if (g.rows[15 - i] > 0) {
  264.             break;
  265.         }
  266.         --end_row;
  267.     }
  268.     return end_row;
  269. }
  270.  
  271.  
  272. void encode_v6(font const& f, std::vector<uint8_t>& buffer)
  273. {
  274.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  275.  
  276.     encode_header(f, buffer);
  277.     simple_bitstream b(buffer);
  278.     for (glyph const& g : f.glyphs) {
  279.         // Code using 1 byte
  280.         b.write_bits(g.code, 8);
  281.  
  282.         uint32_t end_row(find_end_row(g));
  283.         for (uint32_t i(0); i < end_row; ++i) {
  284.             uint16_t row(g.rows[i]);
  285.             if (row == 0) {
  286.                 // Empty row
  287.                 b.write_bits(OP_EMPTY, 2);
  288.                 continue;
  289.             }
  290.  
  291.             // Find nearest identical preceding row in this glyph
  292.             uint8_t offset(find_nearest_copy(g, i));
  293.             if (offset) {
  294.                 // Copy with non-zero offset
  295.                 b.write_bits(OP_COPY, 2);
  296.                 b.write_bits(offset - 1, 4);
  297.             } else {
  298.                 // Verbatim row
  299.                 b.write_bits(OP_VERBATIM, 2);
  300.                 b.write_bits(row, 12);
  301.             }
  302.         }
  303.         if (end_row < 16) {
  304.             // End the glyph (any remaining rows are empty)
  305.             b.write_bits(OP_END, 2);
  306.         }
  307.     }
  308. }
  309.  
  310. void find_max_glyph_size(font const& f, uint32_t& max_end_row, uint32_t& column_count)
  311. {
  312.     uint16_t column_mask(0);
  313.     max_end_row = 0;
  314.     for (glyph const& g : f.glyphs) {
  315.         max_end_row = std::max(max_end_row, find_end_row(g));
  316.  
  317.         for (uint32_t i(0); i < 16; ++i) {
  318.             column_mask |= g.rows[i];
  319.         }
  320.     }
  321.  
  322.     column_count = 12;
  323.     for (; column_count > 0; --column_count) {
  324.         if (column_mask >> (column_count - 1)) {
  325.             break;
  326.         }
  327.     }
  328. }
  329.  
  330.  
  331. void encode_v7(font const& f, std::vector<uint8_t>& buffer)
  332. {
  333.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  334.  
  335.     encode_header(f, buffer);
  336.  
  337.     uint32_t max_end_row, column_count;
  338.     find_max_glyph_size(f, max_end_row, column_count);
  339.  
  340.     simple_bitstream b(buffer);
  341.  
  342.     b.write_bits(column_count - 1, 4);
  343.     b.write_bits(max_end_row - 1, 4);
  344.  
  345.     for (glyph const& g : f.glyphs) {
  346.         // Code using 1 byte
  347.         b.write_bits(g.code, 8);
  348.  
  349.         uint32_t end_row(find_end_row(g));
  350.         for (uint32_t i(0); i < end_row; ++i) {
  351.             uint16_t row(g.rows[i]);
  352.             if (row == 0) {
  353.                 // Empty row
  354.                 b.write_bits(OP_EMPTY, 2);
  355.                 continue;
  356.             }
  357.  
  358.             // Find nearest identical preceding row in this glyph
  359.             uint8_t offset(find_nearest_copy(g, i));
  360.             if (offset) {
  361.                 // Copy with non-zero offset
  362.                 b.write_bits(OP_COPY, 2);
  363.                 b.write_bits(offset - 1, 4);
  364.             } else {
  365.                 // Verbatim row
  366.                 b.write_bits(OP_VERBATIM, 2);
  367.                 b.write_bits(row, column_count);
  368.             }
  369.         }
  370.         if (end_row < max_end_row) {
  371.             // End the glyph (any remaining rows are empty)
  372.             b.write_bits(OP_END, 2);
  373.         }
  374.     }
  375. }
  376.  
  377. #include "arithmetic_codec.h"
  378.  
  379. void encode_v8(font const& f, std::vector<uint8_t>& buffer)
  380. {
  381.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  382.  
  383.     uint32_t max_end_row, column_count;
  384.     find_max_glyph_size(f, max_end_row, column_count);
  385.  
  386.     Arithmetic_Codec codec(1 << 18);
  387.     Adaptive_Bit_Model pixel_model;
  388.     Adaptive_Data_Model opcode_model(4);
  389.     Adaptive_Data_Model offset_model(15);
  390.     Static_Data_Model ascii_model;
  391.     ascii_model.set_distribution(256);
  392.     Static_Data_Model column_model;
  393.     column_model.set_distribution(12);
  394.     Static_Data_Model row_model;
  395.     row_model.set_distribution(16);
  396.  
  397.     codec.start_encoder();
  398.  
  399.     for (uint8_t c : f.header) {
  400.         codec.encode(c, ascii_model);
  401.     }
  402.     codec.encode(0, ascii_model);
  403.  
  404.     codec.encode(column_count - 1, column_model);
  405.     codec.encode(max_end_row - 1, row_model);
  406.  
  407.     for (glyph const& g : f.glyphs) {
  408.         // Code using 1 byte
  409.         codec.encode(g.code, ascii_model);
  410.  
  411.         uint32_t end_row(find_end_row(g));
  412.         for (uint32_t i(0); i < end_row; ++i) {
  413.             uint16_t row(g.rows[i]);
  414.             if (row == 0) {
  415.                 // Empty row
  416.                 codec.encode(OP_EMPTY, opcode_model);
  417.                 continue;
  418.             }
  419.  
  420.             // Find nearest identical preceding row in this glyph
  421.             uint8_t offset(find_nearest_copy(g, i));
  422.             if (offset) {
  423.                 // Copy with non-zero offset
  424.                 codec.encode(OP_COPY, opcode_model);
  425.                 codec.encode(offset - 1, offset_model);
  426.             } else {
  427.                 // Verbatim row
  428.                 codec.encode(OP_VERBATIM, opcode_model);
  429.                 for (uint32_t c(column_count); c > 0; --c) {
  430.                     codec.encode((row >> (c - 1)) & 1, pixel_model);
  431.                 }
  432.             }
  433.         }
  434.         if (end_row < max_end_row) {
  435.             // End the glyph (any remaining rows are empty)
  436.             codec.encode(OP_END, opcode_model);
  437.         }
  438.     }
  439.  
  440.     uint32_t payload_size(codec.stop_encoder());
  441.     uint8_t* payload_buffer(codec.buffer());
  442.  
  443.     buffer.resize(payload_size);
  444.     std::copy(payload_buffer, payload_buffer + payload_size, buffer.begin());
  445. }
  446.  
  447. void encode_v9(font const& f, std::vector<uint8_t>& buffer)
  448. {
  449.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  450.  
  451.     uint32_t max_end_row, column_count;
  452.     find_max_glyph_size(f, max_end_row, column_count);
  453.  
  454.     Arithmetic_Codec codec(1 << 18);
  455.     Adaptive_Bit_Model pixel_model[2];
  456.     Adaptive_Data_Model opcode_model(4);
  457.     Adaptive_Data_Model offset_model(15);
  458.     Static_Data_Model ascii_model;
  459.     ascii_model.set_distribution(256);
  460.     Static_Data_Model column_model;
  461.     column_model.set_distribution(12);
  462.     Static_Data_Model row_model;
  463.     row_model.set_distribution(16);
  464.  
  465.     codec.start_encoder();
  466.  
  467.     for (uint8_t c : f.header) {
  468.         codec.encode(c, ascii_model);
  469.     }
  470.     codec.encode(0, ascii_model);
  471.  
  472.     codec.encode(column_count - 1, column_model);
  473.     codec.encode(max_end_row - 1, row_model);
  474.  
  475.     for (glyph const& g : f.glyphs) {
  476.         // Code using 1 byte
  477.         codec.encode(g.code, ascii_model);
  478.  
  479.         uint32_t end_row(find_end_row(g));
  480.         for (uint32_t i(0); i < end_row; ++i) {
  481.             uint16_t row(g.rows[i]);
  482.             if (row == 0) {
  483.                 // Empty row
  484.                 codec.encode(OP_EMPTY, opcode_model);
  485.                 continue;
  486.             }
  487.  
  488.             // Find nearest identical preceding row in this glyph
  489.             uint8_t offset(find_nearest_copy(g, i));
  490.             if (offset) {
  491.                 // Copy with non-zero offset
  492.                 codec.encode(OP_COPY, opcode_model);
  493.                 codec.encode(offset - 1, offset_model);
  494.             } else {
  495.                 // Verbatim row
  496.                 codec.encode(OP_VERBATIM, opcode_model);
  497.                 uint8_t prev_pixel(0);
  498.                 for (uint32_t c(column_count); c > 0; --c) {
  499.                     uint8_t pixel((row >> (c - 1)) & 1);
  500.                     codec.encode(pixel, pixel_model[prev_pixel]);
  501.                     prev_pixel = pixel;
  502.                 }
  503.             }
  504.         }
  505.         if (end_row < max_end_row) {
  506.             // End the glyph (any remaining rows are empty)
  507.             codec.encode(OP_END, opcode_model);
  508.         }
  509.     }
  510.  
  511.     uint32_t payload_size(codec.stop_encoder());
  512.     uint8_t* payload_buffer(codec.buffer());
  513.  
  514.     buffer.resize(payload_size);
  515.     std::copy(payload_buffer, payload_buffer + payload_size, buffer.begin());
  516. }
  517.  
  518.  
  519. void encode_v10(font const& f, std::vector<uint8_t>& buffer)
  520. {
  521.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  522.  
  523.     uint32_t max_end_row, column_count;
  524.     find_max_glyph_size(f, max_end_row, column_count);
  525.  
  526.     Arithmetic_Codec codec(1 << 18);
  527.     Adaptive_Bit_Model pixel_model[2];
  528.     Adaptive_Data_Model opcode_model[3];
  529.     for (uint32_t i(0); i < 3; ++i) {
  530.         opcode_model[i].set_alphabet(4);
  531.     }
  532.     Adaptive_Data_Model offset_model(15);
  533.     Static_Data_Model ascii_model;
  534.     ascii_model.set_distribution(256);
  535.     Static_Data_Model column_model;
  536.     column_model.set_distribution(12);
  537.     Static_Data_Model row_model;
  538.     row_model.set_distribution(16);
  539.  
  540.     codec.start_encoder();
  541.  
  542.     for (uint8_t c : f.header) {
  543.         codec.encode(c, ascii_model);
  544.     }
  545.     codec.encode(0, ascii_model);
  546.  
  547.     codec.encode(column_count - 1, column_model);
  548.     codec.encode(max_end_row - 1, row_model);
  549.  
  550.     for (glyph const& g : f.glyphs) {
  551.         // Code using 1 byte
  552.         codec.encode(g.code, ascii_model);
  553.  
  554.         uint32_t end_row(find_end_row(g));
  555.         uint8_t prev_opcode(OP_VERBATIM), curr_opcode;
  556.         for (uint32_t i(0); i < end_row; ++i) {
  557.             uint16_t row(g.rows[i]);
  558.             if (row == 0) {
  559.                 // Empty row
  560.                 curr_opcode = OP_EMPTY;
  561.                 codec.encode(curr_opcode, opcode_model[prev_opcode]);
  562.             } else {
  563.                 // Find nearest identical preceding row in this glyph
  564.                 uint8_t offset(find_nearest_copy(g, i));
  565.                 if (offset) {
  566.                     // Copy with non-zero offset
  567.                     curr_opcode = OP_COPY;
  568.                     codec.encode(curr_opcode, opcode_model[prev_opcode]);
  569.                     codec.encode(offset - 1, offset_model);
  570.                 } else {
  571.                     // Verbatim row
  572.                     curr_opcode = OP_COPY;
  573.                     codec.encode(curr_opcode, opcode_model[prev_opcode]);
  574.                     uint8_t prev_pixel(0);
  575.                     for (uint32_t c(column_count); c > 0; --c) {
  576.                         uint8_t pixel((row >> (c - 1)) & 1);
  577.                         codec.encode(pixel, pixel_model[prev_pixel]);
  578.                         prev_pixel = pixel;
  579.                     }
  580.                 }
  581.             }
  582.             prev_opcode = curr_opcode;
  583.         }
  584.         if (end_row < max_end_row) {
  585.             // End the glyph (any remaining rows are empty)
  586.             codec.encode(OP_END, opcode_model[prev_opcode]);
  587.         }
  588.     }
  589.  
  590.     uint32_t payload_size(codec.stop_encoder());
  591.     uint8_t* payload_buffer(codec.buffer());
  592.  
  593.     buffer.resize(payload_size);
  594.     std::copy(payload_buffer, payload_buffer + payload_size, buffer.begin());
  595. }
  596.  
  597.  
  598. void encode_v11(font const& f, std::vector<uint8_t>& buffer)
  599. {
  600.     uint32_t OP_VERBATIM(0), OP_COPY(1), OP_EMPTY(2), OP_END(3);
  601.  
  602.     uint32_t max_end_row, column_count;
  603.     find_max_glyph_size(f, max_end_row, column_count);
  604.  
  605.     Arithmetic_Codec codec(1 << 18);
  606.     Adaptive_Bit_Model presence_model;
  607.     Adaptive_Bit_Model pixel_model[2];
  608.     Adaptive_Data_Model opcode_model[3];
  609.     for (uint32_t i(0); i < 3; ++i) {
  610.         opcode_model[i].set_alphabet(4);
  611.     }
  612.     Adaptive_Data_Model offset_model(15);
  613.     Static_Data_Model ascii_model;
  614.     ascii_model.set_distribution(256);
  615.     Static_Data_Model column_model;
  616.     column_model.set_distribution(12);
  617.     Static_Data_Model row_model;
  618.     row_model.set_distribution(16);
  619.  
  620.     codec.start_encoder();
  621.  
  622.     for (uint8_t c : f.header) {
  623.         codec.encode(c, ascii_model);
  624.     }
  625.     codec.encode(0, ascii_model);
  626.  
  627.     uint8_t first_code(f.glyphs.front().code);
  628.     uint8_t last_code(f.glyphs.back().code);
  629.  
  630.     codec.encode(first_code, ascii_model);
  631.     codec.encode(last_code, ascii_model);
  632.  
  633.     std::vector<bool> glyph_available(256);
  634.     for (glyph const& g : f.glyphs) {
  635.         glyph_available[g.code] = true;
  636.     }
  637.     for (uint32_t i(first_code); i <= last_code; ++i) {
  638.         if (glyph_available[i]) {
  639.             codec.encode(1, presence_model);
  640.         } else {
  641.             codec.encode(0, presence_model);
  642.         }
  643.     }
  644.  
  645.     codec.encode(column_count - 1, column_model);
  646.     codec.encode(max_end_row - 1, row_model);
  647.  
  648.     for (glyph const& g : f.glyphs) {
  649.         uint32_t end_row(find_end_row(g));
  650.         uint8_t prev_opcode(OP_VERBATIM), curr_opcode;
  651.         for (uint32_t i(0); i < end_row; ++i) {
  652.             uint16_t row(g.rows[i]);
  653.             if (row == 0) {
  654.                 // Empty row
  655.                 curr_opcode = OP_EMPTY;
  656.                 codec.encode(curr_opcode, opcode_model[prev_opcode]);
  657.             } else {
  658.                 // Find nearest identical preceding row in this glyph
  659.                 uint8_t offset(find_nearest_copy(g, i));
  660.                 if (offset) {
  661.                     // Copy with non-zero offset
  662.                     curr_opcode = OP_COPY;
  663.                     codec.encode(curr_opcode, opcode_model[prev_opcode]);
  664.                     codec.encode(offset - 1, offset_model);
  665.                 } else {
  666.                     // Verbatim row
  667.                     curr_opcode = OP_COPY;
  668.                     codec.encode(curr_opcode, opcode_model[prev_opcode]);
  669.                     uint8_t prev_pixel(0);
  670.                     for (uint32_t c(column_count); c > 0; --c) {
  671.                         uint8_t pixel((row >> (c - 1)) & 1);
  672.                         codec.encode(pixel, pixel_model[prev_pixel]);
  673.                         prev_pixel = pixel;
  674.                     }
  675.                 }
  676.             }
  677.             prev_opcode = curr_opcode;
  678.         }
  679.         if (end_row < max_end_row) {
  680.             // End the glyph (any remaining rows are empty)
  681.             codec.encode(OP_END, opcode_model[prev_opcode]);
  682.         }
  683.     }
  684.  
  685.     uint32_t payload_size(codec.stop_encoder());
  686.     uint8_t* payload_buffer(codec.buffer());
  687.  
  688.     buffer.resize(payload_size);
  689.     std::copy(payload_buffer, payload_buffer + payload_size, buffer.begin());
  690. }
  691.  
  692.  
  693. int main()
  694. {
  695.     font f(load_font_txt("font_full.txt"));
  696.     f.sort();
  697.  
  698.     std::vector<std::vector<uint8_t>> buf(12);
  699.    
  700.     encode_v0(f, buf[0]);
  701.     encode_v1(f, buf[1]);
  702.     encode_v2(f, buf[2]);
  703.     encode_v3(f, buf[3]);
  704.     encode_v4(f, buf[4]);
  705.     encode_v5(f, buf[5]);
  706.     encode_v6(f, buf[6]);
  707.     encode_v7(f, buf[7]);
  708.     encode_v8(f, buf[8]);
  709.     encode_v9(f, buf[9]);
  710.     encode_v10(f, buf[10]);
  711.     encode_v11(f, buf[11]);
  712.  
  713.     for (uint32_t i(0); i < buf.size(); ++i) {
  714.         std::cout << "Variant " << i << ": " << buf[i].size() << " bytes\n";
  715.     }
  716.  
  717.     return 0;
  718. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement