Files
McBitFont/McBitFont/Form1.cs
2023-05-10 12:15:43 +03:00

586 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices.ComTypes;
using System.Diagnostics;
namespace McBitFont {
public partial class MainForm : Form {
[Serializable]
public struct FrameMiniature {
public FrameMiniature(int cc, int ww, int hh) {
code = cc;
width = ww;
height = hh;
data = new bool[ww, hh];
}
public int code;
public int width;
public int height;
public bool[,] data;
};
[Serializable]
public struct SaveBlock {
public bool monospaced;
public List<FrameMiniature> frames;
}
private FrameMiniature f;
List<FrameMiniature> frames = new List<FrameMiniature>();
private int cellSize = 10;
private int dotWidth, dotHeight;
private int pixelOffset = 5;
private int gap;
private int w, h;
bool monospaced = false;
bool modified = false;
bool prjModified = true;
public MainForm() {
InitializeComponent();
this.dotPanel.MouseWheel += new MouseEventHandler(this.dotPanel_MouseWheel);
}
private void Form1_Load(object sender, EventArgs e) {
lblType.Text = monospaced ? "Monospaced" : "Variable width / Single";
dotWidth = (int)nudX.Value;
dotHeight = (int)nudY.Value;
gap = (cellSize < 5) ? 0 : 1;
w = pixelOffset + dotWidth * (cellSize + gap);
h = pixelOffset + dotHeight * (cellSize + gap);
cbZoom.SelectedIndex = 3;
cbZoom.SelectedIndexChanged += cbZoom_SelectedIndexChanged;
frames.Add(new FrameMiniature(0, dotWidth, dotHeight));
miniList.Items.Add("0", "0 Single", "0");
miniList.Refresh();
f = copyFrame(frames.Find(x => x.code == 0));
ListViewItem_SetSpacing(miniList, 50 + 2, 50 + 22);
}
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
public int MakeLong(short lowPart, short highPart) {
return (int)(((ushort)lowPart) | (uint)(highPart << 16));
}
FrameMiniature copyFrame(FrameMiniature frame) {
var ff = new FrameMiniature(frame.code, frame.width, frame.height);
Array.Copy(frame.data, ff.data, frame.data.Length);
return ff;
}
public void ListViewItem_SetSpacing(ListView listview, short leftPadding, short topPadding) {
const int LVM_FIRST = 0x1000;
const int LVM_SETICONSPACING = LVM_FIRST + 53;
SendMessage(listview.Handle, LVM_SETICONSPACING, IntPtr.Zero, (IntPtr)MakeLong(leftPadding, topPadding));
}
private void dotPanel_MouseWheel(object sender, MouseEventArgs e) {
int t = e.Delta / 120;
if (e.Delta == 0) return;
if (ModifierKeys.HasFlag(Keys.Shift)) {
t += cbZoom.SelectedIndex;
if (t > cbZoom.Items.Count - 1) return;
if (t < 0) return;
cbZoom.SelectedIndex = t;
} else if (ModifierKeys.HasFlag(Keys.Control)) {
if (hScroll.Enabled) {
t = t * -1 * (cellSize + gap) + hScroll.Value;
if (t < hScroll.Minimum) t = hScroll.Minimum;
if (t > hScroll.Maximum) t = hScroll.Maximum;
hScroll.Value = t;
}
} else {
if (vScroll.Enabled) {
t = t * -1 * (cellSize + gap) + vScroll.Value;
if (t < vScroll.Minimum) t = vScroll.Minimum;
if (t > vScroll.Maximum) t = vScroll.Maximum;
vScroll.Value = t;
}
}
}
private void nudX_ValueChanged(object sender, EventArgs e) {
if (monospaced) {
Bitmap bmp;
for (int i = 0; i < frames.Count; i++) {
frames[i] = frameResize(frames[i], (int)nudX.Value, dotHeight);
bmp = getMiniPictue(frames[i]);
string s = frames[i].code.ToString();
ilMiniatures.Images.RemoveByKey(s);
ilMiniatures.Images.Add(s, (Image)bmp);
miniList.Items[s].ImageKey = s;
}
}
prjModified = true;
dotResize((int)nudX.Value, dotHeight);
}
private void nudY_ValueChanged(object sender, EventArgs e) {
Bitmap bmp;
for (int i = 0; i < frames.Count; i++) {
frames[i] = frameResize(frames[i], dotWidth, (int)nudY.Value);
bmp = getMiniPictue(frames[i]);
string s = frames[i].code.ToString();
ilMiniatures.Images.RemoveByKey(s);
ilMiniatures.Images.Add(s, (Image)bmp);
miniList.Items[s].ImageKey = s;
}
prjModified = true;
dotResize(dotWidth, (int)nudY.Value);
}
private FrameMiniature frameResize(FrameMiniature ff, int neww, int newh) {
int oldw = ff.width;
int oldh = ff.height;
int imax, jmax;
bool[,] t;
if (neww < oldw) imax = neww;
else imax = oldw;
if (newh < oldh) jmax = newh;
else jmax = oldh;
ff.width = neww;
ff.height = newh;
t = new bool[neww, newh];
for (int i=0; i<imax; i++) {
for (int j=0;j<jmax; j++) {
t[i, j] = ff.data[i, j];
}
}
ff.data = t;
return ff;
}
private void dotResize(int ww, int hh) {
int imax, jmax;
bool[,] t;
if (ww < dotWidth) imax = ww;
else imax = dotWidth;
if (hh < dotHeight) jmax = hh;
else jmax = dotHeight;
f.width = ww;
f.height = hh;
t = new bool[ww, hh];
for (int i=0; i<imax; i++) {
for (int j=0; j<jmax; j++) {
t[i, j] = f.data[i, j];
}
}
f.data = t;
dotWidth = ww;
dotHeight = hh;
w = pixelOffset + dotWidth * (cellSize + gap);
h = pixelOffset + dotHeight * (cellSize + gap);
cbZoom_SelectedIndexChanged(cbZoom, null);
}
private void cbZoom_SelectedIndexChanged(object sender, EventArgs e) {
cellSize = Convert.ToInt32(cbZoom.Text);
gap = (cellSize < 5) ? 0 : 1;
w = pixelOffset + dotWidth * (cellSize + gap);
h = pixelOffset + dotHeight * (cellSize + gap);
if (w <= dotPanel.Width) {
hScroll.Enabled = false;
hScroll.Value = 0;
} else {
hScroll.Maximum = w - dotPanel.Width + 12;
hScroll.Minimum = 0;
hScroll.Enabled = true;
}
if (h <= dotPanel.Height) {
vScroll.Enabled = false;
vScroll.Value = 0;
} else {
vScroll.Maximum = h - dotPanel.Height + 12;
vScroll.Minimum = 0;
vScroll.Enabled = true;
}
dotPanel.Refresh();
}
private void btnShiftLeft_Click(object sender, EventArgs e) {
bool c;
for (int j = 0; j < dotHeight; j++) {
c = f.data[0, j];
for (int i = 0; i < dotWidth; i++) {
if (i == dotWidth - 1) {
f.data[i, j] = c;
} else {
f.data[i, j] = f.data[i + 1, j];
}
}
}
dotPanel.Refresh();
}
private void btnShiftRight_Click(object sender, EventArgs e) {
bool c;
for (int j = 0; j < dotHeight; j++) {
c = f.data[dotWidth - 1, j];
for (int i = dotWidth - 1; i >= 0; i--) {
if (i == 0) {
f.data[i, j] = c;
} else {
f.data[i, j] = f.data[i - 1, j];
}
}
}
dotPanel.Refresh();
}
private void dotPanel_MouseMove(object sender, MouseEventArgs e) {
if (e.X >= w || e.X <= pixelOffset || e.Y >= h || e.Y <= pixelOffset) return;
int i = (e.X - pixelOffset + hScroll.Value) / (cellSize + gap);
int j = (e.Y - pixelOffset + vScroll.Value) / (cellSize + gap);
label5.Text = i.ToString() + ',' + j.ToString();
if (e.Button == MouseButtons.Left && !f.data[i, j]) {
Graphics g = dotPanel.CreateGraphics();
SolidBrush sbb = new SolidBrush(Color.Black);
f.data[i, j] = true;
int x = pixelOffset + i * (cellSize + gap) - hScroll.Value;
int y = pixelOffset + j * (cellSize + gap) - vScroll.Value;
g.FillRectangle(sbb, x, y, cellSize, cellSize);
modified = true;
}
if (e.Button == MouseButtons.Right && f.data[i, j]) {
Graphics g = dotPanel.CreateGraphics();
SolidBrush sbw = new SolidBrush(Color.White);
f.data[i, j] = false;
int x = pixelOffset + i * (cellSize + gap) - hScroll.Value;
int y = pixelOffset + j * (cellSize + gap) - vScroll.Value;
g.FillRectangle(sbw, x, y, cellSize, cellSize);
modified = true;
}
}
private void btnShiftUp_Click(object sender, EventArgs e) {
bool c;
for (int i = 0; i < dotWidth; i++) {
c = f.data[i, 0];
for (int j = 0; j < dotHeight; j++) {
if (j == dotHeight - 1) {
f.data[i, j] = c;
} else {
f.data[i, j] = f.data[i, j + 1];
}
}
}
dotPanel.Refresh();
}
private void btnShiftDown_Click(object sender, EventArgs e) {
bool c;
for (int i = 0; i < dotWidth; i++) {
c = f.data[i, dotHeight - 1];
for (int j = dotHeight-1; j >= 0; j--) {
if (j == 0) {
f.data[i, j] = c;
} else {
f.data[i, j] = f.data[i, j - 1];
}
}
}
dotPanel.Refresh();
}
private void btnInvert_Click(object sender, EventArgs e) {
for (int i = 0; i < dotWidth; i++) {
for (int j = 0; j < dotHeight; j++) {
f.data[i, j] = !f.data[i, j];
}
}
dotPanel.Refresh();
}
private void btnMirrorX_Click(object sender, EventArgs e) {
int a, b, j;
bool c;
for (j = 0; j < dotHeight; j++) {
a = 0;
b = dotWidth - 1;
while (a < b) {
c = f.data[a, j];
f.data[a, j] = f.data[b, j];
f.data[b, j] = c;
a++;
b--;
}
}
dotPanel.Refresh();
}
private void btnMirrorY_Click(object sender, EventArgs e) {
int a, b, i;
bool c;
for (i = 0; i < dotWidth; i++) {
a = 0;
b = dotHeight - 1;
while (a < b) {
c = f.data[i, a];
f.data[i, a] = f.data[i, b];
f.data[i, b] = c;
a++;
b--;
}
}
dotPanel.Refresh();
}
private void button1_Click(object sender, EventArgs e) {
Export eform = new Export();
eform.ShowDialog();
//outBox.Clear();
//String str;
//Byte b = 0;
//for (ushort i = 0; i < dotWidth; i++) {
// str = "";
// for (ushort j = 0; j < dotHeight; j++) {
// if (j % 8 == 0) b = 0;
// if (f.data[i, j]) {
// b |= (Byte)(1 << (j % 8));
// }
// if ( ((j + 1) % 8 == 0) || j+1 == dotHeight ) {
// if (str.Length > 0) str += " ";
// str += "0x" + Convert.ToString(b, 16).PadLeft(2, '0') + ',';
// }
// }
// outBox.AppendText(str);
// outBox.AppendText(Environment.NewLine);
//}
}
private void button2_Click(object sender, EventArgs e) {
saveFrame();
}
private void saveFrame() {
int index = frames.FindIndex(x => x.code == f.code);
frames[index] = f;
var sizedBMP = getMiniPictue(f);
string s = f.code.ToString();
ilMiniatures.Images.RemoveByKey(s);
ilMiniatures.Images.Add(s, (Image)sizedBMP);
sizedBMP.Dispose();
modified = false;
prjModified = true;
}
private Bitmap getMiniPictue(FrameMiniature m) {
int picSize = (m.width > m.height) ? m.width : m.height;
var bmp = new Bitmap(picSize, picSize);
int imin = m.width < picSize ? (picSize - m.width) / 2 : 0;
int jmin = m.height < picSize ? (picSize - m.height) / 2 : 0;
Color c;
for (int i = 0; i < m.width; i++) {
for (int j = 0; j < m.height; j++) {
c = m.data[i, j] ? Color.Black : Color.White;
bmp.SetPixel(i+imin, j+jmin, c);
}
}
var sizedBMP = new Bitmap(bmp, new Size(50, 50));
bmp.Dispose();
return sizedBMP;
}
private void dotPanel_Paint(object sender, PaintEventArgs e) {
Graphics g = dotPanel.CreateGraphics();
SolidBrush sbb = new SolidBrush(Color.Black);
SolidBrush sbw = new SolidBrush(Color.White);
SolidBrush sb;
Pen p = new Pen(Color.FromArgb(64, Color.Green));
int x, y;
for (int i=0; i<dotWidth; i++) {
x = pixelOffset + i * (cellSize + gap) - hScroll.Value;
if (gap > 0 && i != 0 && (i % 8) == 0) {
g.DrawLine(p, x - 1, pixelOffset - vScroll.Value, x - 1, h);
}
for (int j=0; j<dotHeight; j++) {
y = pixelOffset + j * (cellSize + gap) - vScroll.Value;
if (gap > 0 && i == 0 && j != 0 && (j % 8) == 0) {
g.DrawLine(p, pixelOffset - hScroll.Value, y-1, w, y-1);
}
if (f.data[i, j]) sb = sbb;
else sb = sbw;
g.FillRectangle(sb, x, y, cellSize, cellSize);
}
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
Application.Exit();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e) {
if (prjModified) {
if (MessageBox.Show("The project is modified.\nDo you want to save it first?", "Project was modified!", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) {
saveToolStripMenuItem.PerformClick();
return;
}
}
New form = new New();
if (form.ShowDialog() == DialogResult.OK) {
frames.Clear();
miniList.Clear();
ilMiniatures.Images.Clear();
string append = "";
int neww = (int)form.nudNewX.Value;
int newh = (int)form.nudNewY.Value;
if (form.cbSingle.Checked) {
frames.Add( new FrameMiniature(0, neww, newh));
//f = frames.Find(x => x.code == 0);
append = "Single";
} else {
int i;
if (form.cbNotPrintable.Checked) {
for (i=0; i < 32; i++)
frames.Add(new FrameMiniature(i, neww, newh));
}
if (form.cbLatin.Checked) {
for (i = 32; i < 128; i++)
frames.Add(new FrameMiniature(i, neww, newh));
}
if (form.cbExtended.Checked) {
for (i = 128; i < 256; i++)
frames.Add(new FrameMiniature(i, neww, newh));
}
}
monospaced = form.rbMono.Checked;
foreach (FrameMiniature ff in frames) {
var s = ff.code.ToString();
ilMiniatures.Images.Add(s, (Image)getMiniPictue(ff));
var sss = s + ' ' + append + (char)(ff.code);
//byte[] aaa = { (byte)ff.code}
//Debug.WriteLine(sss.ToString() + Encoding.UTF8.GetString(new byte[] { 0x10, 0x04 }));
miniList.Items.Add(s, s+' '+append+(char)(ff.code), s);
}
nudX.Value =neww;
nudY.Value = newh;
f = copyFrame(frames.First());
dotPanel.Refresh();
miniList.Refresh();
form.Dispose();
}
}
private void miniList_SelectedIndexChanged(object sender, EventArgs e) {
if (miniList.FocusedItem == null) return;
if (modified) {
if (MessageBox.Show("Current symbol is modified.\nDo you want to save the changes?", "Symbol was modified!", MessageBoxButtons.YesNo) == DialogResult.Yes) {
saveFrame();
}
modified = false;
}
var sel = miniList.SelectedItems[0];
int code = Convert.ToInt32(sel.ImageKey);
FrameMiniature ff = copyFrame(frames.Find(x => x.code == code));
nudX.Value = ff.width;
nudY.Value = ff.height;
f = ff;
dotPanel.Refresh();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e) {
if (dlgSave.ShowDialog() == DialogResult.OK) {
SaveBlock sav;
sav.monospaced = monospaced;
sav.frames = frames;
BinaryFormatter formatter = new BinaryFormatter();
using (Stream ms = File.OpenWrite(dlgSave.FileName)) {
formatter.Serialize(ms, sav);
ms.Close();
}
prjModified = false;
}
}
private void openToolStripMenuItem_Click(object sender, EventArgs e) {
if (prjModified) {
if (MessageBox.Show("The project is modified.\nDo you want to save it first?", "Project was modified!", MessageBoxButtons.YesNo) == DialogResult.Yes) {
saveToolStripMenuItem.PerformClick();
return;
}
}
if (dlgOpen.ShowDialog() == DialogResult.OK) {
//MessageBox.Show(dlgOpen.FileName);
SaveBlock sav;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream fs = File.Open(dlgOpen.FileName, FileMode.Open)) {
sav = (SaveBlock)formatter.Deserialize(fs);
fs.Close();
}
monospaced = sav.monospaced;
frames = sav.frames;
miniList.Items.Clear();
ilMiniatures.Images.Clear();
foreach (FrameMiniature ff in frames) {
var s = ff.code.ToString();
ilMiniatures.Images.Add(s, (Image)getMiniPictue(ff));
miniList.Items.Add(s, s + ' ' + (char)ff.code, s);
}
nudX.ValueChanged -= nudX_ValueChanged;
nudY.ValueChanged -= nudY_ValueChanged;
nudX.Value = frames.First().width;
nudY.Value = frames.First().height;
dotResize((int)nudX.Value, (int)nudY.Value);
nudX.ValueChanged += nudX_ValueChanged;
nudY.ValueChanged += nudY_ValueChanged;
f = copyFrame(frames.First());
dotPanel.Refresh();
miniList.Refresh();
modified = false;
prjModified = false;
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {
if (prjModified) {
if (MessageBox.Show("The project is modified.\nAre you sure you want to quit?", "Are you sure?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) {
e.Cancel = true;
} else {
e.Cancel = false;
}
}
}
private void scroll_ValueChanged(object sender, EventArgs e) {
dotPanel.Refresh();
}
}
}