970 lines
35 KiB
C#
970 lines
35 KiB
C#
using MessagePack;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
|
|
|
|
namespace McBitFont {
|
|
public partial class MainForm : Form {
|
|
|
|
|
|
[Serializable]
|
|
[MessagePackObject]
|
|
public struct FrameMiniature {
|
|
public FrameMiniature(int cc, int ww, int hh) {
|
|
code = cc;
|
|
width = ww;
|
|
height = hh;
|
|
data = new bool[ww, hh];
|
|
}
|
|
[Key(0)]
|
|
public int code;
|
|
[Key(1)]
|
|
public int width;
|
|
[Key(2)]
|
|
public int height;
|
|
[Key(3)]
|
|
public bool[,] data;
|
|
};
|
|
|
|
[Serializable]
|
|
[MessagePackObject]
|
|
public struct SaveBlock {
|
|
[Key(4)]
|
|
public bool monospaced;
|
|
[Key(5)]
|
|
public int codepage;
|
|
[Key(6)]
|
|
public int baseline;
|
|
[Key(7)]
|
|
public List<FrameMiniature> frames;
|
|
}
|
|
|
|
private FrameMiniature f;
|
|
public List<FrameMiniature> frames = new List<FrameMiniature>();
|
|
private CanvasHistory history = new();
|
|
private int cellSize = 10;
|
|
public int dotWidth, dotHeight;
|
|
private int pixelOffset = 5;
|
|
private int gap;
|
|
private int w, h;
|
|
public bool monospaced = false;
|
|
bool modified = false;
|
|
bool prjModified = false;
|
|
public const string version = "2.0";
|
|
public string prjName = "Untitled";
|
|
public string prjFileName = "";
|
|
public int codepage = 1251;
|
|
private FrameMiniature fbuf;
|
|
private bool fbuffer = false;
|
|
public int baseline = 0;
|
|
public bool set_base = false;
|
|
|
|
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("000", "000 Single", "000");
|
|
miniList.Refresh();
|
|
miniList.Items[0].Selected = true;
|
|
miniList.Select();
|
|
f = CopyFrame(frames.Find(x => x.code == 0));
|
|
|
|
ListViewItem_SetSpacing(miniList, 50 + 2, 50 + 22);
|
|
|
|
this.Text = "McBitFont " + version + " - " + prjName;
|
|
|
|
fbuf = new FrameMiniature(0, dotWidth, dotHeight);
|
|
|
|
// Chek for arguments
|
|
if (Environment.GetCommandLineArgs().Length > 1) {
|
|
LoadProject(Environment.GetCommandLineArgs()[1]);
|
|
}
|
|
|
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|
}
|
|
|
|
[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.Control)) {
|
|
t += cbZoom.SelectedIndex;
|
|
if (t > cbZoom.Items.Count - 1) return;
|
|
if (t < 0) return;
|
|
cbZoom.SelectedIndex = t;
|
|
} else if (ModifierKeys.HasFlag(Keys.Shift)) {
|
|
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) {
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
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().PadLeft(3, '0');
|
|
ilMiniatures.Images.RemoveByKey(s);
|
|
ilMiniatures.Images.Add(s, (Image)bmp);
|
|
miniList.Items[s].ImageKey = s;
|
|
}
|
|
} else {
|
|
if (nudX.Focused) modified = true;
|
|
}
|
|
prjModified = true;
|
|
dotResize((int)nudX.Value, dotHeight);
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
|
|
private void nudY_ValueChanged(object sender, EventArgs e) {
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
Bitmap bmp;
|
|
for (int i = 0; i < frames.Count; i++) {
|
|
frames[i] = frameResize(frames[i], frames[i].width, (int)nudY.Value);
|
|
bmp = getMiniPictue(frames[i]);
|
|
string s = frames[i].code.ToString().PadLeft(3, '0');
|
|
ilMiniatures.Images.RemoveByKey(s);
|
|
ilMiniatures.Images.Add(s, (Image)bmp);
|
|
miniList.Items[s].ImageKey = s;
|
|
}
|
|
if (nudY.Focused) modified = true;
|
|
prjModified = true;
|
|
dotResize(dotWidth, (int)nudY.Value);
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
|
|
private FrameMiniature frameResize(FrameMiniature ff, int neww, int newh) {
|
|
int oldw = ff.width;
|
|
int oldh = ff.height;
|
|
int di = 0, dj = 0;
|
|
int imax, jmax;
|
|
bool[,] t;
|
|
|
|
if (chkLeftSide.Checked) di = oldw - neww;
|
|
if (chkTopSide.Checked) dj = oldh - newh;
|
|
|
|
imax = (neww < oldw) ? neww : oldw;
|
|
jmax = (newh < oldh) ? newh : oldh;
|
|
if (neww > oldw) imax -= di;
|
|
if (newh > oldh) jmax -= dj;
|
|
|
|
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++) {
|
|
if (i + di >= 0 && j + dj >= 0) t[i, j] = ff.data[i + di, j + dj];
|
|
}
|
|
}
|
|
ff.data = t;
|
|
|
|
return ff;
|
|
}
|
|
|
|
private void dotResize(int ww, int hh) {
|
|
f = frameResize(f, ww, hh);
|
|
dotWidth = ww;
|
|
dotHeight = hh;
|
|
w = pixelOffset + dotWidth * (cellSize + gap);
|
|
h = pixelOffset + dotHeight * (cellSize + gap);
|
|
cbZoom_SelectedIndexChanged(cbZoom, null);
|
|
|
|
// Re-create history object
|
|
history = new CanvasHistory();
|
|
}
|
|
|
|
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;
|
|
|
|
history.AddPre(f);
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void btnShiftRight_Click(object sender, EventArgs e) {
|
|
bool c;
|
|
|
|
history.AddPre(f);
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private bool mouseDown = false;
|
|
private bool fChanged = false;
|
|
private void dotPanel_MouseMove(object sender, MouseEventArgs e) {
|
|
// Moving baseline
|
|
Rectangle rect1, rect2;
|
|
if (set_base) {
|
|
|
|
int yy = pixelOffset + baseline * (cellSize + gap) - vScroll.Value - 1;
|
|
rect1 = new Rectangle(pixelOffset, yy, w, 2);
|
|
baseline = (e.Y - pixelOffset + vScroll.Value) / (cellSize + gap);
|
|
|
|
if (baseline >= dotHeight) baseline = dotHeight - 1;
|
|
if (baseline < 0) baseline = 0;
|
|
|
|
yy = pixelOffset + baseline * (cellSize + gap) - vScroll.Value - 1;
|
|
rect2 = new Rectangle(pixelOffset, yy, w, 2);
|
|
|
|
dotPanel.Invalidate(rect1);
|
|
dotPanel.Invalidate(rect2);
|
|
|
|
if (e.Button == MouseButtons.Left) {
|
|
set_base = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (e.X >= w || e.X <= pixelOffset || e.Y >= h || e.Y <= pixelOffset) return;
|
|
// Change coordinates in the panel
|
|
int i = (e.X - pixelOffset + hScroll.Value) / (cellSize + gap);
|
|
int j = (e.Y - pixelOffset + vScroll.Value) / (cellSize + gap);
|
|
label5.Text = i.ToString() + ',' + j.ToString();
|
|
|
|
// history management
|
|
if (e.Button != MouseButtons.None && !mouseDown) {
|
|
mouseDown = true;
|
|
history.AddPre(f, false);
|
|
}
|
|
if (e.Button == MouseButtons.None && mouseDown) {
|
|
mouseDown = false;
|
|
if (!fChanged) {
|
|
history.Remove(false);
|
|
} else {
|
|
fChanged = false;
|
|
history.ApplyAdded();
|
|
history.AddPost(f);
|
|
}
|
|
CheckHistoryButtons();
|
|
}
|
|
|
|
// Paint black / white
|
|
if (e.Button == MouseButtons.Left && !f.data[i, j]) {
|
|
f.data[i, j] = true;
|
|
fChanged = true;
|
|
int x = pixelOffset + i * (cellSize + gap) - hScroll.Value;
|
|
int y = pixelOffset + j * (cellSize + gap) - vScroll.Value;
|
|
modified = true;
|
|
rect1 = new Rectangle(x, y, cellSize, cellSize);
|
|
dotPanel.Invalidate(rect1);
|
|
}
|
|
if (e.Button == MouseButtons.Right && f.data[i, j]) {
|
|
f.data[i, j] = false;
|
|
fChanged = true;
|
|
int x = pixelOffset + i * (cellSize + gap) - hScroll.Value;
|
|
int y = pixelOffset + j * (cellSize + gap) - vScroll.Value;
|
|
modified = true;
|
|
rect1 = new Rectangle(x, y, cellSize, cellSize);
|
|
dotPanel.Invalidate(rect1);
|
|
}
|
|
|
|
}
|
|
|
|
private void btnShiftUp_Click(object sender, EventArgs e) {
|
|
bool c;
|
|
|
|
history.AddPre(f);
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void btnShiftDown_Click(object sender, EventArgs e) {
|
|
bool c;
|
|
|
|
history.AddPre(f);
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void btnInvert_Click(object sender, EventArgs e) {
|
|
history.AddPre(f);
|
|
for (int i = 0; i < dotWidth; i++) {
|
|
for (int j = 0; j < dotHeight; j++) {
|
|
f.data[i, j] = !f.data[i, j];
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void btnMirrorX_Click(object sender, EventArgs e) {
|
|
int a, b, j;
|
|
bool c;
|
|
|
|
history.AddPre(f);
|
|
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--;
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void btnMirrorY_Click(object sender, EventArgs e) {
|
|
int a, b, i;
|
|
bool c;
|
|
|
|
history.AddPre(f);
|
|
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--;
|
|
}
|
|
}
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
private void button1_Click(object sender, EventArgs e) {
|
|
if (modified) {
|
|
if (MessageBox.Show("Current symbol is modified.\nDo you want to save the changes?", "Symbol was modified!", MessageBoxButtons.YesNo) == DialogResult.Yes) {
|
|
saveFrame();
|
|
} else {
|
|
f = CopyFrame(frames.Find(x => x.code == f.code));
|
|
}
|
|
modified = false;
|
|
}
|
|
|
|
|
|
Export eform = new Export(this);
|
|
eform.ShowDialog();
|
|
}
|
|
|
|
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().PadLeft(3, '0');
|
|
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);
|
|
}
|
|
}
|
|
Bitmap sbmp = new Bitmap(50, 50);
|
|
using (Graphics g = Graphics.FromImage(sbmp)) {
|
|
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
g.PixelOffsetMode = PixelOffsetMode.Half;
|
|
g.DrawImage(bmp, 0, 0, 50, 50);
|
|
}
|
|
bmp.Dispose();
|
|
return sbmp;
|
|
}
|
|
|
|
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, (baseline == j ? y + 1 : y), cellSize, (baseline == j ? cellSize - 1 : cellSize));
|
|
}
|
|
}
|
|
|
|
if (baseline > 0 && gap > 0) {
|
|
x = pixelOffset - hScroll.Value;
|
|
y = pixelOffset + baseline * (cellSize + gap) - vScroll.Value;
|
|
g.DrawLine(
|
|
new Pen(Color.Blue, 2),
|
|
x, y,
|
|
w, y
|
|
);
|
|
}
|
|
}
|
|
|
|
private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
Application.Exit();
|
|
}
|
|
|
|
public string decodeSymbol(int code) {
|
|
var enc = Encoding.GetEncoding(codepage);
|
|
if (code < 32) return "";
|
|
return enc.GetString(new byte[] { (byte)code });
|
|
}
|
|
|
|
private FrameMiniature fillFrame(FrameMiniature ff, Font font, int sx, int sy) {
|
|
string s = decodeSymbol(ff.code);
|
|
Bitmap bmp = new Bitmap(ff.width, ff.height);
|
|
Graphics g = Graphics.FromImage(bmp);
|
|
g.Clear(Color.White);
|
|
g.SmoothingMode = SmoothingMode.None;
|
|
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
g.PixelOffsetMode = PixelOffsetMode.Half;
|
|
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
|
|
g.DrawString(s, font, Brushes.Black, sx, sy);
|
|
g.Flush();
|
|
|
|
for (int i = 0; i < ff.width; i++)
|
|
for (int j = 0; j < ff.height; j++) {
|
|
if (bmp.GetPixel(i, j).Name != "ffffffff")
|
|
ff.data[i, j] = true;
|
|
}
|
|
|
|
bmp.Dispose();
|
|
g.Dispose();
|
|
return ff;
|
|
}
|
|
|
|
private void newToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
checkModifiedFrame();
|
|
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(this);
|
|
if (form.ShowDialog() == DialogResult.OK) {
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
frames.Clear();
|
|
miniList.Clear();
|
|
ilMiniatures.Images.Clear();
|
|
|
|
string append = "";
|
|
int neww = (int)form.nudNewX.Value;
|
|
int newh = (int)form.nudNewY.Value;
|
|
nudX.Value = neww;
|
|
nudY.Value = newh;
|
|
FrameMiniature newf;
|
|
if (form.cbSingle.Checked) {
|
|
frames.Add(new FrameMiniature(0, neww, newh));
|
|
//f = frames.Find(x => x.code == 0);
|
|
append = "Single";
|
|
monospaced = false;
|
|
} else {
|
|
int i, imin, imax;
|
|
if (form.cbDigits.Checked) {
|
|
imin = 48;
|
|
imax = 57;
|
|
} else {
|
|
if (form.cbNotPrintable.Checked) imin = 0;
|
|
else if (form.cbLatin.Checked) imin = 32;
|
|
else imin = 128;
|
|
|
|
if (form.cbExtended.Checked) imax = 255;
|
|
else if (form.cbLatin.Checked) imax = 127;
|
|
else imax = 31;
|
|
}
|
|
|
|
|
|
for (i = imin; i <= imax; i++) {
|
|
newf = new FrameMiniature(i, neww, newh);
|
|
if (form.cbFontBased.Checked) newf = fillFrame(newf, form.dlgFont.Font, (int)form.nudShiftX.Value, (int)form.nudShiftY.Value);
|
|
frames.Add(newf);
|
|
}
|
|
|
|
monospaced = form.rbMono.Checked;
|
|
}
|
|
makeVarWidthToolStripMenuItem.Visible = monospaced;
|
|
lblType.Text = monospaced ? "Monospaced" : "Variable width / Single";
|
|
codepage = (form.cbEncoding.SelectedItem as New.EncodingItem).Code;
|
|
foreach (FrameMiniature ff in frames) {
|
|
var s = ff.code.ToString().PadLeft(3, '0');
|
|
ilMiniatures.Images.Add(s, (Image)getMiniPictue(ff));
|
|
var sss = decodeSymbol(ff.code);
|
|
miniList.Items.Add(s, s + ' ' + append + sss, s);
|
|
}
|
|
f = CopyFrame(frames.First());
|
|
form.Dispose();
|
|
|
|
baseline = 0;
|
|
|
|
prjName = "Untitled";
|
|
prjFileName = "";
|
|
this.Text = "McBitFont " + version + " - " + prjName;
|
|
modified = false;
|
|
checkForAdd();
|
|
fbuffer = false;
|
|
miniList.Refresh();
|
|
dotPanel.Refresh();
|
|
|
|
// Re-create history object
|
|
history = new CanvasHistory();
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
}
|
|
|
|
private void MiniList_SelectedIndexChanged(object sender, EventArgs e) {
|
|
if (miniList.FocusedItem == null) return;
|
|
checkModifiedFrame();
|
|
if (miniList.SelectedItems.Count == 0) {
|
|
removeSymbolToolStripMenuItem.Enabled = false;
|
|
removeBeforeToolStripMenuItem.Enabled = false;
|
|
removeAfterToolStripMenuItem.Enabled = false;
|
|
copyToolStripMenuItem.Enabled = false;
|
|
pasteToolStripMenuItem.Enabled = false;
|
|
return;
|
|
//miniList.Items[0].Selected = true;
|
|
}
|
|
|
|
// Clear history
|
|
history.Clear();
|
|
|
|
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();
|
|
ff = frames.Find(x => x.code == code);
|
|
if (frames.Count > 1 && (ff.Equals(frames.First()) || ff.Equals(frames.Last()))) {
|
|
removeSymbolToolStripMenuItem.Enabled = true;
|
|
} else {
|
|
removeSymbolToolStripMenuItem.Enabled = false;
|
|
}
|
|
copyToolStripMenuItem.Enabled = true;
|
|
if (ff.Equals(frames.First())) {
|
|
removeBeforeToolStripMenuItem.Enabled = false;
|
|
removeAfterToolStripMenuItem.Enabled = true;
|
|
} else if (ff.Equals(frames.Last())) {
|
|
removeBeforeToolStripMenuItem.Enabled = true;
|
|
removeAfterToolStripMenuItem.Enabled = false;
|
|
} else {
|
|
removeBeforeToolStripMenuItem.Enabled = true;
|
|
removeAfterToolStripMenuItem.Enabled = true;
|
|
}
|
|
|
|
if (fbuffer) pasteToolStripMenuItem.Enabled = true;
|
|
else pasteToolStripMenuItem.Enabled = false;
|
|
}
|
|
|
|
private void SaveToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
checkModifiedFrame();
|
|
if (dlgSave.ShowDialog() == DialogResult.OK) {
|
|
SaveProject(dlgSave.FileName);
|
|
}
|
|
}
|
|
|
|
private void LoadProject(string filename) {
|
|
SaveBlock sav;
|
|
|
|
using (FileStream fs = File.Open(filename, FileMode.Open)) {
|
|
sav = MessagePackSerializer.Deserialize<SaveBlock>(fs);
|
|
fs.Close();
|
|
}
|
|
monospaced = sav.monospaced;
|
|
codepage = sav.codepage;
|
|
baseline = sav.baseline;
|
|
lblType.Text = monospaced ? "Monospaced" : "Variable width / Single";
|
|
frames = sav.frames;
|
|
makeVarWidthToolStripMenuItem.Visible = monospaced;
|
|
miniList.Items.Clear();
|
|
ilMiniatures.Images.Clear();
|
|
foreach (FrameMiniature ff in frames) {
|
|
var s = ff.code.ToString().PadLeft(3, '0');
|
|
var sss = decodeSymbol(ff.code);
|
|
ilMiniatures.Images.Add(s, (Image)getMiniPictue(ff));
|
|
miniList.Items.Add(s, s + ' ' + sss, 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;
|
|
|
|
prjFileName = filename;
|
|
prjName = Path.GetFileNameWithoutExtension(filename);
|
|
this.Text = "McBitFont " + version + " - " + prjName;
|
|
checkForAdd();
|
|
fbuffer = false;
|
|
}
|
|
|
|
private void SaveProject(string filename) {
|
|
SaveBlock sav;
|
|
sav.monospaced = monospaced;
|
|
sav.frames = frames;
|
|
sav.codepage = codepage;
|
|
sav.baseline = baseline;
|
|
|
|
using (Stream ms = File.OpenWrite(filename)) {
|
|
MessagePackSerializer.Serialize(ms, sav);
|
|
ms.Close();
|
|
}
|
|
prjModified = false;
|
|
prjName = Path.GetFileNameWithoutExtension(filename);
|
|
prjFileName = filename;
|
|
this.Text = "McBitFont " + version + " - " + prjName;
|
|
}
|
|
|
|
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) {
|
|
saveAsToolStripMenuItem.PerformClick();
|
|
return;
|
|
}
|
|
}
|
|
if (dlgOpen.ShowDialog() == DialogResult.OK) {
|
|
LoadProject(dlgOpen.FileName);
|
|
}
|
|
}
|
|
|
|
private void removeSymbolToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
if (miniList.SelectedItems.Count == 0) {
|
|
removeSymbolToolStripMenuItem.Enabled = false;
|
|
return;
|
|
}
|
|
var sel = miniList.SelectedItems[0].ImageKey;
|
|
int code = Convert.ToInt32(miniList.SelectedItems[0].ImageKey);
|
|
FrameMiniature ff = frames.Find(x => x.code == code);
|
|
frames.Remove(ff);
|
|
miniList.SelectedItems[0].Remove();
|
|
//miniList.Items[0].Selected = true;
|
|
}
|
|
|
|
private void prependSymbolToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
FrameMiniature ff;
|
|
if (sender == prependSymbolToolStripMenuItem) {
|
|
ff = new FrameMiniature(frames.First().code - 1, dotWidth, dotHeight);
|
|
frames.Insert(0, ff);
|
|
} else {
|
|
ff = new FrameMiniature(frames.Last().code + 1, dotWidth, dotHeight);
|
|
frames.Add(ff);
|
|
}
|
|
|
|
var s = ff.code.ToString().PadLeft(3, '0');
|
|
ilMiniatures.Images.Add(s, (Image)getMiniPictue(ff));
|
|
var sss = decodeSymbol(ff.code);
|
|
miniList.Items.Add(s, s + ' ' + sss, s);
|
|
checkForAdd();
|
|
}
|
|
|
|
private void checkForAdd() {
|
|
if (frames.Count > 1) {
|
|
if (frames.First().code > 0) prependSymbolToolStripMenuItem.Enabled = true;
|
|
else prependSymbolToolStripMenuItem.Enabled = false;
|
|
if (frames.Last().code < 255) appendSymbolToolStripMenuItem.Enabled = true;
|
|
else appendSymbolToolStripMenuItem.Enabled = false;
|
|
} else {
|
|
prependSymbolToolStripMenuItem.Enabled = false;
|
|
appendSymbolToolStripMenuItem.Enabled = false;
|
|
}
|
|
}
|
|
|
|
private void copyToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
fbuffer = true;
|
|
fbuf = CopyFrame(f);
|
|
pasteToolStripMenuItem.Enabled = true;
|
|
}
|
|
|
|
private void pasteToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
if (fbuf.width == f.width && fbuf.height == f.height) {
|
|
Array.Copy(fbuf.data, f.data, fbuf.data.Length);
|
|
} else {
|
|
var wmax = (fbuf.width > f.width) ? f.width : fbuf.width;
|
|
var hmax = (fbuf.height > f.height) ? f.height : fbuf.height;
|
|
|
|
for (int i = 0; i < wmax; i++) {
|
|
for (int j = 0; j < hmax; j++) {
|
|
f.data[i, j] = fbuf.data[i, j];
|
|
}
|
|
}
|
|
}
|
|
|
|
dotPanel.Refresh();
|
|
modified = true;
|
|
}
|
|
|
|
private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
About form = new About();
|
|
form.ShowDialog();
|
|
}
|
|
|
|
private void btnBaseline_Click(object sender, EventArgs e) {
|
|
set_base = !set_base;
|
|
}
|
|
|
|
// Check modified / Save frame
|
|
private void checkModifiedFrame() {
|
|
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;
|
|
}
|
|
}
|
|
|
|
private void saveToolStripMenuItem_Click_1(object sender, EventArgs e) {
|
|
if (prjFileName == "") {
|
|
saveAsToolStripMenuItem.PerformClick();
|
|
} else {
|
|
checkModifiedFrame();
|
|
SaveProject(prjFileName);
|
|
}
|
|
|
|
}
|
|
|
|
private void btnClear_Click(object sender, EventArgs e) {
|
|
history.AddPre(f);
|
|
Array.Clear(f.data, 0, f.data.Length);
|
|
history.AddPost(f);
|
|
CheckHistoryButtons();
|
|
modified = true;
|
|
dotPanel.Refresh();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
// Remove all before or after specified symbol
|
|
private void removeBA(bool before) {
|
|
if (miniList.SelectedItems.Count == 0) {
|
|
removeBeforeToolStripMenuItem.Enabled = false;
|
|
removeAfterToolStripMenuItem.Enabled = false;
|
|
return;
|
|
}
|
|
int step = before ? -1 : 1;
|
|
var sel = miniList.SelectedItems[0].ImageKey;
|
|
int code = Convert.ToInt32(sel);
|
|
int findex;
|
|
|
|
while (miniList.Items.ContainsKey((code + step).ToString().PadLeft(3, '0'))) {
|
|
code += step;
|
|
findex = frames.FindIndex(x => x.code == code);
|
|
frames.RemoveAt(findex);
|
|
miniList.Items.RemoveByKey(code.ToString().PadLeft(3, '0'));
|
|
}
|
|
//dotPanel.Refresh();
|
|
miniList.Refresh();
|
|
prjModified = true;
|
|
}
|
|
|
|
private void removeBeforeToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
removeBA(true);
|
|
}
|
|
|
|
private void removeAfterToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
removeBA(false);
|
|
}
|
|
|
|
private void makeVarWidthToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
monospaced = false;
|
|
makeVarWidthToolStripMenuItem.Visible = false;
|
|
lblType.Text = "Variable width / Single";
|
|
prjModified = true;
|
|
}
|
|
|
|
public void CheckHistoryButtons() {
|
|
undoToolStripMenuItem.Enabled = history.Undos > 0;
|
|
redoToolStripMenuItem.Enabled = history.Redos > 0;
|
|
|
|
undoToolStripMenuItem.Text = "Undo (" + history.Undos + ")";
|
|
redoToolStripMenuItem.Text = "Redo (" + history.Redos + ")";
|
|
}
|
|
|
|
private void editToolStripMenuItem_DropDownOpening(object sender, EventArgs e) {
|
|
CheckHistoryButtons();
|
|
}
|
|
|
|
private void undoToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
history.Undo(f);
|
|
dotPanel.Refresh();
|
|
CheckHistoryButtons();
|
|
}
|
|
|
|
private void redoToolStripMenuItem_Click(object sender, EventArgs e) {
|
|
history.Redo(f);
|
|
dotPanel.Refresh();
|
|
CheckHistoryButtons();
|
|
}
|
|
}
|
|
}
|