/// <summary> /// Update the preview for the pixel font /// </summary> private void UpdatePixelFontPreview() { Console.WriteLine("UpdatePreview called..."); SingleCharInfoDisplay ciDisplay = null; foreach (Control c in _fontDesignPage.Controls) { if (c.GetType() == typeof(SingleCharInfoDisplay)) { ciDisplay = (SingleCharInfoDisplay)c; break; } } if (ciDisplay != null) { Bitmap bmp = null; if (_previewPanel.BackgroundImage != null) { _previewPanel.BackgroundImage.Dispose(); _previewPanel.BackgroundImage = null; } //refresh everytime...//TODO::improve bmp = DrawFontPreviewBitmap(ciDisplay.FontSize.Width, ciDisplay.FontSize.Height, ciDisplay.FontPixelsMap, Color.Aqua, Color.Black); _previewPanel.BackgroundImage = (Image)bmp; _previewPanel.BackgroundImageLayout = ImageLayout.Center; _previewPanel.BackgroundImage = bmp; _previewPanel.Update(); _previewPanel.Refresh(); } }
/// <summary> /// Paint all the pixel drawing containers /// </summary> private void PopulateFontDesignCanvas() { _fontDesignPage.Controls.Clear(); char c = ((AsciiCode)_asciiCodeCbx.Items[_asciiCodeCbx.SelectedIndex]).Value; if (!_allPixelMaps.ContainsKey(c)) { return; //not yet populated } SingleCharInfoDisplay ciDisplay = _allPixelMaps[c]; /* * Each UInt32 entry in the array, represents a single row of pixels (max 32 pixels). * If height in pixel is 7 pixels, then we need to read 7 rows. * If width in pixel is 5 pixels, then for each entry, we need to check for bit '1' from left to right */ ciDisplay.Left = (_fontDesignPage.Left + _fontDesignPage.Width - ciDisplay.Width) / 2; ciDisplay.Top = (_fontDesignPage.Top + _fontDesignPage.Height - ciDisplay.Height) / 2; if (_previewPanel.BackgroundImage != null) { _previewPanel.BackgroundImage.Dispose(); _previewPanel.BackgroundImage = DrawFontPreviewBitmap(ciDisplay.FontSize.Width, ciDisplay.FontSize.Height, ciDisplay.FontPixelsMap, Color.Aqua, Color.Black); } SuspendLayout(); _fontDesignPage.Controls.Add(ciDisplay); ResumeLayout(); Update(); Refresh(); }
/// <summary> /// Called when the pixel is clicked on the editor /// </summary> /// <param name="source"></param> private void OnPixelClicked(SingleCharInfoDisplay source) { Console.WriteLine("OnPixelClicked..."); //Show current character being edited if (source.BackColor != Color.LightGoldenrodYellow) { source.BackColor = Color.LightGoldenrodYellow; source.Update(); source.Refresh(); } _docDirty = true; UpdatePixelFontPreview(); }
/// <summary> /// User wants to create a new file /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnNewFile(object sender, EventArgs e) { if (_docDirty && MessageBox.Show(this, "Current changes not saved. Do you want to proceed?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } FontSizeForm itemSizeDlg = new FontSizeForm(); if (itemSizeDlg.ShowDialog(this) == DialogResult.OK) { _docDirty = false; Cursor = Cursors.WaitCursor; _asciiCodeCbx.Items.Clear(); if (_allPixelMaps != null) { _allPixelMaps.Clear(); } _allPixelMaps = null; _filePath = null; Text = "Pixel Font Generator"; //Populate the supported character codes PopulateAsciiCodes(); //A new file is being created...populate the character editor _allPixelMaps = new Dictionary <char, SingleCharInfoDisplay>(); foreach (AsciiCode ac in _asciiCodeCbx.Items) { SingleCharInfoDisplay ciDisplay = new SingleCharInfoDisplay((byte)itemSizeDlg.PixelHeight, (byte)itemSizeDlg.PixelWidth, ac.Value); ciDisplay.CharEdit += OnPixelClicked; _allPixelMaps.Add(ac.Value, ciDisplay); } _canvasTabs.SelectTab(0); _asciiCodeCbx.SelectedIndex = 0;//select the first item by default PopulateFontDesignCanvas(); _fontSizeLbl.Text = itemSizeDlg.PixelWidth + " (W) X " + itemSizeDlg.PixelHeight + " (H)"; Cursor = Cursors.Default; } }
/// <summary> /// Export font file as an image /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnExportToImage(object sender, EventArgs e) { if (_allPixelMaps == null || _allPixelMaps.Count == 0) { MessageBox.Show(this, "Nothing to export", "Pixel Font Generator", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SaveFileDialog saveFile = new SaveFileDialog() { AddExtension = true, CheckPathExists = true, DefaultExt = ".bmp", Filter = "Image Files|*.bmp", OverwritePrompt = true, RestoreDirectory = true, ValidateNames = true }; if (saveFile.ShowDialog(this) == DialogResult.OK) { try { int totalItems = _allPixelMaps.Count; int fontHeight = _allPixelMaps[(char)' '].FontSize.Height; int fontWidth = _allPixelMaps[(char)' '].FontSize.Width; //create a new bitmap to hold all images int xPos = 0; int yPos = 0; int sqrt = (int)Math.Ceiling(Math.Sqrt(totalItems)); int bmpHW = 50;//48x48 BMP with 2 pixel gutter width Bitmap container = new Bitmap(sqrt * bmpHW, sqrt * bmpHW); Graphics canvas = Graphics.FromImage(container); foreach (var c in _allPixelMaps.Keys) { //get each font pixel map and construct the font SingleCharInfoDisplay ciDisplay = _allPixelMaps[c]; Bitmap fontImage = DrawFontPreviewBitmap(fontWidth, fontHeight, ciDisplay.FontPixelsMap, Color.Black, Color.WhiteSmoke); Bitmap fontContainer = new Bitmap(bmpHW - 2, bmpHW - 2); Graphics fcGraphics = Graphics.FromImage(fontContainer); fcGraphics.FillRectangle(Brushes.Black, 0, 0, fontContainer.Width, 15); fcGraphics.FillRectangle(Brushes.WhiteSmoke, 0, 15, 48, 48 - 15); fcGraphics.DrawString(c + "", new Font("Arial", 8), Brushes.White, 20, 0); fcGraphics.DrawImage(fontImage, (fontContainer.Width - fontWidth) / 2, (33 - fontHeight) / 2 + 15); canvas.DrawImage(fontContainer, xPos, yPos); xPos += bmpHW; if (xPos > container.Width) { xPos = 1; //reset to left yPos += bmpHW; } fontImage.Dispose(); fontContainer.Dispose(); } container.Save(saveFile.FileName); MessageBox.Show(this, "Font image exported successfully", "Pixel Font Generator", MessageBoxButtons.OK, MessageBoxIcon.Information); container.Dispose(); } catch (Exception ex) { MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// Open a font file to edit /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnFileOpen(object sender, EventArgs e) { if (_docDirty) { if (MessageBox.Show(this, "You have unsaved changes. If you proceed without saving the current document, your changes will be lost. " + "Do you want to proceed?", "Save Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } else { _docDirty = false; } } OpenFileDialog ofDlg = new OpenFileDialog() { AddExtension = true, CheckFileExists = true, CheckPathExists = true, DefaultExt = ".cs", Filter = "C# Files|*.cs", Multiselect = false, RestoreDirectory = true, ShowReadOnly = true }; if (ofDlg.ShowDialog(this) == DialogResult.OK) { try { StreamReader sr = File.OpenText(ofDlg.FileName); String contents = sr.ReadToEnd(); sr.Close(); string firstId = "//7ede8a4c-223c-4389-a683-cb2c5de448d5"; string secondId = "//f3b635d2-e762-4110-b202-488f5b6ca5df"; //Validate file if (contents.IndexOf(firstId) < 0 || contents.IndexOf(secondId) < 0) { MessageBox.Show(this, "Invalid font mapping file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Cursor = Cursors.WaitCursor; string temp = ""; //First extract pixel map string pixelMap = ""; temp = contents.Substring(contents.IndexOf(secondId) + secondId.Length); temp = temp.Substring(0, temp.IndexOf(secondId)); pixelMap = temp.Replace("\t", "").Trim(); //Now extract size contents = contents.Replace("\r\n", ""); temp = contents.Substring(contents.IndexOf(firstId) + firstId.Length + 2); string wh = temp.Substring(0, temp.IndexOf("//")); int fontWidth = int.Parse(wh.Split(new char[] { ';' })[0]); int fontHeight = int.Parse(wh.Split(new char[] { ';' })[1]); string[] lines = pixelMap.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); _allPixelMaps = new Dictionary <char, SingleCharInfoDisplay>(); char c = (char)32; foreach (string line in lines) { if (line.Trim().StartsWith("//")) { Console.WriteLine("Reading..." + line); //extract the char if (line.Trim().StartsWith("// Space")) { c = (char)32; } else { c = line.Trim().Substring(3)[0]; } } else { List <UInt32> charPixels = new List <UInt32>(); string[] pixelVals = line.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (string entry in pixelVals) { charPixels.Add(Convert.ToUInt32(entry.Trim(), 16)); } SingleCharInfoDisplay ciDisplay = new SingleCharInfoDisplay((byte)fontHeight, (byte)fontWidth, c); ciDisplay.SetPixelMap(charPixels.ToArray()); ciDisplay.CharEdit += OnPixelClicked; _allPixelMaps.Add(c, ciDisplay); } } //Now setup window state PopulateAsciiCodes(); _asciiCodeCbx.SelectedIndex = 0; _fontSizeLbl.Text = fontWidth + " (W) X " + fontHeight + " (H)"; Text = "Pixel Font Generator :" + ofDlg.FileName; _filePath = ofDlg.FileName; //Now redraw PopulateFontDesignCanvas(); } } catch (Exception ex) { MessageBox.Show(this, "Seems like an invalid file !\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { Cursor = Cursors.Default; } } }