Files
McBitFont/McBitFont/Export.cs
2023-05-11 17:21:07 +03:00

298 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
namespace McBitFont {
public partial class Export : Form {
private MainForm mainForm;
//private List<string> comments = new List<string>();
private Dictionary<string, string> comments = new Dictionary<string, string>();
public Export(object sender) {
InitializeComponent();
mainForm = (MainForm)sender;
}
private void Export_Load(object sender, EventArgs e) {
var groupBoxes = Controls.OfType<GroupBox>();
foreach (var gb in groupBoxes) {
var comboBoxes = gb.Controls.OfType<ComboBox>();
foreach (var cb in comboBoxes) {
cb.SelectedIndex = 0;
}
}
comments.Add("header",
"// File generated by McBitFont " + MainForm.version + "\n" +
"// made by Anton Mukhin (mcfly@mcflyer.ru)\n" +
"//\n" +
"//\n"
);
comments.Add("scan_order", "// Scan order: ");
comments.Add("scan_hdir", "// Horizontal direction: ");
comments.Add("scan_vdir", "// Vertical direction: ");
comments.Add("num_bit_order", "// Bit order: ");
comments.Add("num_base", "// Numbers base: ");
comments.Add("num_size", "// Numbers size: ");
comments.Add("text_format", "// Text format: ");
comments.Add("text_lines", "// Numbers per line: ");
comments.Add("font_header_map",
"// Font header map:\n" +
"// width; // Font width in pixels\n" +
"// height; // Font height in pixels\n" +
"// space; // Font space in pixels\n" +
"// first; // First character code\n" +
"// last; // Last character code\n"
);
}
private void cbOrder_SelectedIndexChanged(object sender, EventArgs e) {
switch (cbOrder.SelectedIndex) {
case 0: // Columns
cbBitOrder.Items[0] = "LSB Top";
cbBitOrder.Items[1] = "MSB Top";
cbLines.Items[0] = "1 Column per line";
break;
case 1: // Rows
cbBitOrder.Items[0] = "LSB Left";
cbBitOrder.Items[1] = "MSB Left";
cbLines.Items[0] = "1 Row per line";
break;
}
}
private void btnGenerate_Click(object sender, EventArgs e) {
string output = "";
txtOutput.Clear();
bool com = cbComments.Checked;
bool hdr = cbHeader.Checked;
int lines = cbLines.SelectedIndex;
int format = cbFormat.SelectedIndex;
if (com) {
//Header comments
output += comments["header"];
output += comments["scan_order"] + cbOrder.Text + "\n";
output += comments["scan_hdir"] + cbHDir.Text + "\n";
output += comments["scan_vdir"] + cbVDir.Text + "\n\n";
output += comments["num_bit_order"] + cbBitOrder.Text + "\n";
output += comments["num_base"] + cbNumBase.Text + "\n";
output += comments["num_size"] + cbNumSize.Text + "\n\n";
output += comments["text_format"] + cbFormat.Text + "\n";
output += comments["text_lines"] + cbLines.Text + "\n\n";
if (hdr) {
// comment about meta header map
output += comments["font_header_map"] + "\n\n";
}
}
int imin, jmin, imax, jmax, idir, jdir;
if (cbOrder.SelectedIndex == 0) {
if (cbHDir.SelectedIndex == 0) {
// Columns; Left to right
imin = 0;
imax = mainForm.dotWidth;
idir = 1;
} else {
// Columns; Right to left
imin = mainForm.dotWidth - 1;
imax = -1;
idir = -1;
}
if (cbVDir.SelectedIndex == 0) {
// Columns; Top to bottom
jmin = 0;
jmax = mainForm.dotHeight;
jdir = 1;
} else {
// Columns; Bottom to top
jmin = mainForm.dotHeight - 1;
jmax = -1;
jdir = -1;
}
} else {
if (cbHDir.SelectedIndex == 0) {
// Rows; Left to right
jmin = 0;
jmax = mainForm.dotHeight;
jdir = 1;
} else {
// Rows; Right to left
jmin = mainForm.dotHeight - 1;
jmax = -1;
jdir = -1;
}
if (cbVDir.SelectedIndex == 0) {
// Rows; Top to bottom
imin = 0;
imax = mainForm.dotWidth;
idir = 1;
} else {
// Rows; Bottom to top
imin = mainForm.dotWidth - 1;
imax = -1;
idir = -1;
}
}
ushort bits = 8;
string dataType = "uint8_t";
switch (cbNumSize.SelectedIndex) {
case 0:
bits = 8;
dataType = "uint8_t";
break;
case 1:
bits = 16;
dataType = "uint16_t";
break;
case 2:
bits = 32;
dataType = "uint32_t";
break;
}
int nbase = 16;
string prefix = "0x";
string pref = "";
int pad = 2;
switch (cbNumBase.SelectedIndex) {
case 0:
nbase = 16;
prefix = "0x";
pad = cbZeroes.Checked ? bits / 4 : 0;
break;
case 1:
nbase = 2;
prefix = "0b";
pad = cbZeroes.Checked ? bits : 0;
break;
case 2:
nbase = 10;
prefix = "";
pad = 0;
break;
}
// Array definition
if ( format == 0 || format == 1 ) output += "const " + dataType + " " + mainForm.prjName + "[] = {\n";
// Brackets for 2D array definition
string obracket = format == 1 ? "{ " : "";
string cbracket = format == 1 ? " }" : "";
// Number output counter
int numcount = 0;
if (com) output += " // Data:\n";
foreach ( MainForm.FrameMiniature f in mainForm.frames) {
// For each frame
string str;
uint b = 0; // current number bits
int t, x, y; // t - calculated bit number; x - actual x; y - actual y
if (com && lines != 1) {
// Comments enabled and other than "1 symbol per line" selected
// Print a symbol comment before its data
output += " // " + f.code.ToString() + " --> " + mainForm.decodeSymbol(f.code) + "\n";
}
if (lines == 1) {
// "1 symbol per line" - new line offset
output += " ";
numcount = 0;
}
for (int i = imin; i != imax; i += idir) {
if (lines == 0) {
// "Column/Row per line" - new line offset
output += " " + obracket;
numcount = 0;
}
for (int j = jmin; j != jmax; j += jdir) {
if (jdir < 0) t = jmin - j;
else t = j;
if (t % bits == 0) b = 0;
if (cbOrder.SelectedIndex == 0) { // Columns
x = i; y = j;
} else { // Rows
x = j; y = i;
}
if (f.data[x, y]) {
if ((cbBitOrder.SelectedIndex == 0 && jdir > 0) || (cbBitOrder.SelectedIndex == 1 && jdir < 0)) {
// LSB on top/Left
b |= (uint)(1 << (t % bits));
} else {
// MSB on top/Left
b |= (uint)(1 << (bits - (t % bits) - 1));
}
}
if (((t + 1) % bits == 0) || j + jdir == jmax) {
// we have filled a number with bits - let's post it
// should we post a comma before the number?
output += numcount == 0 ? "" : ", ";
// should we post a prefix to the number?
pref = (!cbZeroes.Checked && ((b < 10 && nbase == 16) || (b < 2 && nbase == 2))) ? "" : prefix;
output += pref + Convert.ToString(b, nbase).PadLeft(pad, '0');
// count posted numbers
numcount++;
}
}
if (lines == 0) {
// "Column/Row per line" - closing line
output += cbracket + (i+idir!=imax ? "," : "") + "\n";
}
}
if (lines == 1) {
// "1 symbol per line" - closing line
if (com) {
//...with a comment
output += " // " + f.code.ToString() + " --> " + mainForm.decodeSymbol(f.code);
}
output += "\n";
}
}
// Close array definition
output += "};\n";
txtOutput.Text = output;
txtOutput.SelectionStart = 0;
txtOutput.ScrollToCaret();
}
private void cbFormat_SelectedIndexChanged(object sender, EventArgs e) {
if (cbFormat.SelectedIndex == 1 && cbHeader.Checked) {
MessageBox.Show("Cannot pack the font meta header into 2D array!\nChoose 1D array or disable the meta header.\n(Setting array format to 1D array)", "No header in 2D array!", MessageBoxButtons.OK, MessageBoxIcon.Information);
cbFormat.SelectedIndex = 0;
}
if (cbFormat.SelectedIndex == 1) {
cbLines.SelectedIndex = 0;
cbLines.Enabled = false;
} else {
cbLines.Enabled = true;
}
}
}
}