diff --git a/McBitFont/Form1.Designer.cs b/McBitFont/Form1.Designer.cs index 7cf13db..ec0e2e2 100644 --- a/McBitFont/Form1.Designer.cs +++ b/McBitFont/Form1.Designer.cs @@ -82,6 +82,7 @@ CodeShiftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); canvasToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ClearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + FillToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); shiftUpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); shiftDownToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); shiftLeftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -99,7 +100,7 @@ chkTopSide = new System.Windows.Forms.CheckBox(); chkHexCodes = new System.Windows.Forms.CheckBox(); label3 = new System.Windows.Forms.Label(); - FillToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + chkRectSelect = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)nudX).BeginInit(); ((System.ComponentModel.ISupportInitialize)nudY).BeginInit(); panel1.SuspendLayout(); @@ -111,7 +112,7 @@ // dotPanel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; dotPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - dotPanel.BackColor = System.Drawing.SystemColors.ControlDark; + dotPanel.BackColor = System.Drawing.Color.Gray; dotPanel.Location = new System.Drawing.Point(14, 31); dotPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); dotPanel.Name = "dotPanel"; @@ -120,6 +121,7 @@ dotPanel.Paint += dotPanel_Paint; dotPanel.MouseDown += dotPanel_MouseMove; dotPanel.MouseMove += dotPanel_MouseMove; + dotPanel.MouseUp += dotPanel_MouseMove; dotPanel.Resize += cbZoom_SelectedIndexChanged; // // nudX @@ -191,7 +193,7 @@ cbZoom.Location = new System.Drawing.Point(619, 52); cbZoom.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); cbZoom.Name = "cbZoom"; - cbZoom.Size = new System.Drawing.Size(68, 23); + cbZoom.Size = new System.Drawing.Size(75, 23); cbZoom.TabIndex = 6; cbZoom.TabStop = false; toolTip1.SetToolTip(cbZoom, "Canvas zoom level"); @@ -476,7 +478,7 @@ hScroll.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; hScroll.Location = new System.Drawing.Point(14, 609); hScroll.Name = "hScroll"; - hScroll.Size = new System.Drawing.Size(454, 21); + hScroll.Size = new System.Drawing.Size(427, 21); hScroll.TabIndex = 14; hScroll.ValueChanged += scroll_ValueChanged; // @@ -494,7 +496,7 @@ // lblCoords.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; lblCoords.AutoSize = true; - lblCoords.Location = new System.Drawing.Point(616, 132); + lblCoords.Location = new System.Drawing.Point(616, 138); lblCoords.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); lblCoords.Name = "lblCoords"; lblCoords.Size = new System.Drawing.Size(24, 15); @@ -745,6 +747,15 @@ ClearToolStripMenuItem.ToolTipText = "Clear canvas"; ClearToolStripMenuItem.Click += btnClear_Click; // + // FillToolStripMenuItem + // + FillToolStripMenuItem.Image = Properties.Resources.Canvas_Fill; + FillToolStripMenuItem.Name = "FillToolStripMenuItem"; + FillToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.B; + FillToolStripMenuItem.Size = new System.Drawing.Size(197, 22); + FillToolStripMenuItem.Text = "Fill canvas"; + FillToolStripMenuItem.Click += btnFill_Click; + // // shiftUpToolStripMenuItem // shiftUpToolStripMenuItem.Image = Properties.Resources.z_uo; @@ -909,26 +920,29 @@ // label3.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; label3.AutoSize = true; - label3.Location = new System.Drawing.Point(615, 117); + label3.Location = new System.Drawing.Point(615, 123); label3.Name = "label3"; label3.Size = new System.Drawing.Size(45, 15); label3.TabIndex = 21; label3.Text = "Cursor:"; // - // FillToolStripMenuItem + // chkRectSelect // - FillToolStripMenuItem.Image = Properties.Resources.Canvas_Fill; - FillToolStripMenuItem.Name = "FillToolStripMenuItem"; - FillToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.B; - FillToolStripMenuItem.Size = new System.Drawing.Size(197, 22); - FillToolStripMenuItem.Text = "Fill canvas"; - FillToolStripMenuItem.Click += btnFill_Click; + chkRectSelect.Appearance = System.Windows.Forms.Appearance.Button; + chkRectSelect.Location = new System.Drawing.Point(620, 92); + chkRectSelect.Name = "chkRectSelect"; + chkRectSelect.Size = new System.Drawing.Size(74, 27); + chkRectSelect.TabIndex = 23; + chkRectSelect.Text = "Rect Select"; + chkRectSelect.UseVisualStyleBackColor = true; + chkRectSelect.CheckedChanged += chkRectSelect_CheckedChanged; // // MainForm // AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; ClientSize = new System.Drawing.Size(915, 647); + Controls.Add(chkRectSelect); Controls.Add(chkHexCodes); Controls.Add(label3); Controls.Add(chkTopSide); @@ -1047,6 +1061,7 @@ private System.Windows.Forms.CheckBox chkHexCodes; private System.Windows.Forms.Button btnFill; private System.Windows.Forms.ToolStripMenuItem FillToolStripMenuItem; + private System.Windows.Forms.CheckBox chkRectSelect; } } diff --git a/McBitFont/Form1.cs b/McBitFont/Form1.cs index b2bfc54..581c7dc 100644 --- a/McBitFont/Form1.cs +++ b/McBitFont/Form1.cs @@ -55,22 +55,29 @@ namespace McBitFont { private int gap; private int w, h; public bool monospaced = false; - bool modified = false; - bool prjModified = false; + private bool modified = false; + private bool prjModified = false; public const string version = "2.0"; public string prjName = "Untitled"; public string prjFileName = ""; - public int codepage = 1251; + private int codepage = 1251; private FrameMiniature fbuf; private bool fbuffer = false; - public int baseline = 0; - public bool set_base = false; + private int baseline = 0; + private bool set_base = false; + private Point selection1, selection2; + public MainForm() { InitializeComponent(); this.dotPanel.MouseWheel += new MouseEventHandler(this.DotPanel_MouseWheel); } + private void SetNewWH() { + w = pixelOffset + dotWidth * (cellSize + gap); + h = pixelOffset + dotHeight * (cellSize + gap); + } + private void Form1_Load(object sender, EventArgs e) { lblType.Text = monospaced ? "Monospaced" : "Variable width / Single"; tsmiMakeVarWidth.Visible = monospaced; @@ -78,9 +85,11 @@ namespace McBitFont { dotWidth = (int)nudX.Value; dotHeight = (int)nudY.Value; + selection1 = new Point(0, 0); + selection2 = new Point(dotWidth - 1, dotHeight - 1); + gap = (cellSize < 5) ? 0 : 1; - w = pixelOffset + dotWidth * (cellSize + gap); - h = pixelOffset + dotHeight * (cellSize + gap); + SetNewWH(); cbZoom.SelectedIndex = 3; @@ -230,8 +239,7 @@ namespace McBitFont { f = FrameResize(f, ww, hh); dotWidth = ww; dotHeight = hh; - w = pixelOffset + dotWidth * (cellSize + gap); - h = pixelOffset + dotHeight * (cellSize + gap); + SetNewWH(); cbZoom_SelectedIndexChanged(cbZoom, null); // Re-create history object @@ -242,8 +250,7 @@ namespace McBitFont { cellSize = Convert.ToInt32(cbZoom.Text); gap = (cellSize < 5) ? 0 : 1; - w = pixelOffset + dotWidth * (cellSize + gap); - h = pixelOffset + dotHeight * (cellSize + gap); + SetNewWH(); if (w <= dotPanel.Width) { hScroll.Enabled = false; hScroll.Value = 0; @@ -265,14 +272,76 @@ namespace McBitFont { dotPanel.Refresh(); } - private void btnShiftLeft_Click(object sender, EventArgs e) { + // Deconstruct selection coords from points + private (int x, int y, int x2, int y2) RectSelCoords() { + int x, y, x2, y2; + if (chkRectSelect.Checked) { + x = selection1.X; y = selection1.Y; + x2 = selection2.X; y2 = selection2.Y; + } else { + x = y = 0; + x2 = dotWidth - 1; y2 = dotHeight - 1; + } + return (x, y, x2, y2); + } + + private void btnShiftUp_Click(object sender, EventArgs e) { + int x, y, x2, y2; bool c; + (x, y, x2, y2) = RectSelCoords(); + 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) { + for (int i = x; i <= x2; i++) { + c = f.data[i, y]; + for (int j = y; j <= y2; j++) { + if (j == y2) { + 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) { + int x, y, x2, y2; + bool c; + + (x, y, x2, y2) = RectSelCoords(); + + history.AddPre(f); + for (int i = x; i <= x2; i++) { + c = f.data[i, y2]; + for (int j = y2; j >= y; j--) { + if (j == y) { + 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 btnShiftLeft_Click(object sender, EventArgs e) { + int x, y, x2, y2; + bool c; + + (x, y, x2, y2) = RectSelCoords(); + + history.AddPre(f); + for (int j = y; j <= y2; j++) { + c = f.data[x, j]; + for (int i = x; i <= x2; i++) { + if (i == x2) { f.data[i, j] = c; } else { f.data[i, j] = f.data[i + 1, j]; @@ -286,13 +355,15 @@ namespace McBitFont { } private void btnShiftRight_Click(object sender, EventArgs e) { + int x, y, x2, y2; bool c; + (x, y, x2, y2) = RectSelCoords(); 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) { + for (int j = y; j <= y2; j++) { + c = f.data[x2, j]; + for (int i = x2; i >= x; i--) { + if (i == x) { f.data[i, j] = c; } else { f.data[i, j] = f.data[i - 1, j]; @@ -308,6 +379,9 @@ namespace McBitFont { private bool mouseDown = false; private bool fChanged = false; private void dotPanel_MouseMove(object sender, MouseEventArgs e) { + var rectSel = chkRectSelect.Checked; + bool rectSelUpdated = false; + // Moving baseline Rectangle rect1, rect2; if (set_base) { @@ -337,21 +411,67 @@ namespace McBitFont { int j = (e.Y - pixelOffset + vScroll.Value) / (cellSize + gap); lblCoords.Text = i.ToString() + ',' + j.ToString(); - // history management + // History and Rectangle selection management + if (rectSel && mouseDown && e.Button != MouseButtons.None) { + if (selection2.X != i || selection2.Y != j) { + rectSelUpdated = true; + selection2.X = i; + selection2.Y = j; + } + } if (e.Button != MouseButtons.None && !mouseDown) { mouseDown = true; - history.AddPre(f, false); + if (rectSel) { + selection1.X = i; + selection1.Y = j; + selection2.X = i; + selection2.Y = j; + dotPanel.Invalidate(); + } else history.AddPre(f, false); } if (e.Button == MouseButtons.None && mouseDown) { mouseDown = false; - if (!fChanged) { - history.Remove(false); + if (rectSel) { + NormPoints(ref selection1, ref selection2); + dotPanel.Invalidate(); } else { - fChanged = false; - history.ApplyAdded(); - history.AddPost(f); + if (!fChanged) { + history.Remove(false); + } else { + fChanged = false; + history.ApplyAdded(); + history.AddPost(f); + } + CheckHistoryButtons(); } - CheckHistoryButtons(); + } + + if (rectSel) { + if (mouseDown && rectSelUpdated) { + int x, xx, x2, xx2, y, yy, y2, yy2; + + Point p1 = new(selection1.X, selection1.Y); + Point p2 = new(selection2.X, selection2.Y); + NormPoints(ref p1, ref p2); + x = pixelOffset + (p1.X - 1) * (cellSize + gap) - hScroll.Value - 1; + y = pixelOffset + (p1.Y - 1) * (cellSize + gap) - vScroll.Value - 1; + x2 = pixelOffset + (p2.X + 2) * (cellSize + gap) - hScroll.Value - 1; + y2 = pixelOffset + (p2.Y + 2) * (cellSize + gap) - vScroll.Value - 1; + xx = x + 2 * (cellSize + gap); + yy = y + 2 * (cellSize + gap); + xx2 = x2 - 2 * (cellSize + gap); + yy2 = y2 - 2 * (cellSize + gap); + + Region reg, reg2; + reg = new(new Rectangle(x, y, x2 - x + 1, y2 - y + 1)); + reg.Exclude(new Rectangle(x + 1, y + 1, x2 - x - 1, y2 - y - 1)); + reg2 = new(new Rectangle(xx, yy, xx2 - xx + 1, yy2 - yy + 1)); + reg2.Exclude(new Rectangle(xx + 1, yy + 1, xx2 - xx - 1, yy2 - yy - 1)); + reg.Union(reg2); + + dotPanel.Invalidate(reg); + } + return; } // Paint black / white @@ -376,53 +496,19 @@ namespace McBitFont { } - 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) { + int x, y, x2, y2; + history.AddPre(f); - for (int i = 0; i < dotWidth; i++) { - for (int j = 0; j < dotHeight; j++) { + + (x, y, x2, y2) = RectSelCoords(); + + for (int i = x; i <= x2; i++) { + for (int j = y; j <= y2; j++) { f.data[i, j] = !f.data[i, j]; } } + history.AddPost(f); CheckHistoryButtons(); modified = true; @@ -430,13 +516,15 @@ namespace McBitFont { } private void btnMirrorX_Click(object sender, EventArgs e) { - int a, b, j; + int a, b, j, x, y, x2, y2; bool c; + (x, y, x2, y2) = RectSelCoords(); + history.AddPre(f); - for (j = 0; j < dotHeight; j++) { - a = 0; - b = dotWidth - 1; + for (j = y; j <= y2; j++) { + a = x; + b = x2; while (a < b) { c = f.data[a, j]; f.data[a, j] = f.data[b, j]; @@ -452,13 +540,15 @@ namespace McBitFont { } private void btnMirrorY_Click(object sender, EventArgs e) { - int a, b, i; + int a, b, i, x, y, x2, y2; bool c; + (x, y, x2, y2) = RectSelCoords(); + history.AddPre(f); - for (i = 0; i < dotWidth; i++) { - a = 0; - b = dotHeight - 1; + for (i = x; i <= x2; i++) { + a = y; + b = y2; while (a < b) { c = f.data[i, a]; f.data[i, a] = f.data[i, b]; @@ -532,34 +622,57 @@ namespace McBitFont { SolidBrush sbb = new SolidBrush(Color.Black); SolidBrush sbw = new SolidBrush(Color.White); SolidBrush sb; - Pen p = new Pen(Color.FromArgb(64, Color.Green)); + Pen p = new Pen(Color.FromArgb(100, 20, 120, 20)); int x, y; + // Draw the grid for (int i = 0; i < dotWidth; i++) { x = pixelOffset + i * (cellSize + gap) - hScroll.Value; + // Green lines every 8 cells 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; + // Green lines every 8 cells if (gap > 0 && i == 0 && j != 0 && (j % 8) == 0) { g.DrawLine(p, pixelOffset - hScroll.Value, y - 1, w, y - 1); } + // Fill the cell with color 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)); } } + // Draw the baseline 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 - ); + + Pen sbBase = new(Color.Blue, 2); + g.DrawLine(sbBase, x, y, w, y); } + + // Draw the Rect selection + if (chkRectSelect.Checked) { + Point p1 = new(selection1.X, selection1.Y); + Point p2 = new(selection2.X, selection2.Y); + NormPoints(ref p1, ref p2); + + Pen sbRect = new(Color.FromArgb(200, 0, 200, 0), 3); + x = pixelOffset + p1.X * (cellSize + gap) - hScroll.Value - 1; + y = pixelOffset + p1.Y * (cellSize + gap) - vScroll.Value - 1; + int ww = pixelOffset + (p2.X + 1) * (cellSize + gap) - hScroll.Value - x - 1; + int hh = pixelOffset + (p2.Y + 1) * (cellSize + gap) - vScroll.Value - y - 1; + g.DrawRectangle(sbRect, x, y, ww, hh); + } + } + + private static void NormPoints(ref Point a, ref Point b) { + int bot; + if (a.X > b.X) { bot = a.X; a.X = b.X; b.X = bot; } + if (a.Y > b.Y) { bot = a.Y; a.Y = b.Y; b.Y = bot; } } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { @@ -940,15 +1053,17 @@ namespace McBitFont { } private void FillFrame(bool val) { + int x, y, x2, y2; + history.AddPre(f); - if (!val) Array.Clear(f.data); - else - for (int i = 0; i < f.width; i++) { - for (int j = 0; j < f.height; j++) { - f.data[i, j] = val; - } + (x, y, x2, y2) = RectSelCoords(); + + for (int i = x; i <= x2; i++) { + for (int j = y; j <= y2; j++) { + f.data[i, j] = val; } + } history.AddPost(f); CheckHistoryButtons(); @@ -1116,5 +1231,8 @@ namespace McBitFont { } } + private void chkRectSelect_CheckedChanged(object sender, EventArgs e) { + dotPanel.Refresh(); + } } } diff --git a/TODO.txt b/TODO.txt index 6c5cf0e..ae9ef9c 100644 --- a/TODO.txt +++ b/TODO.txt @@ -18,7 +18,7 @@ V Ability to make monospaced font a variable width one V Undo/Redo for canvas changes V Image import from a file - Import from a text array -- Rectangle selection to mass-paint, shift and mirror pixels +V Rectangle selection to mass-paint, shift and mirror pixels etc... V "Packed" fonts export V "Bytes total comment in export