586 lines
22 KiB
C#
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();
|
|
}
|
|
|
|
}
|
|
}
|