在MCU项目中,准备自己写个简单的UI,在中文文字显示,打算选择 UCDOS 中的 HZK16,为了查看字体文件,用C#写了个简单的查看器,并导出数据为C语言数组(因为所用的STM32F103VET片内flash有512K,可以容纳字库,不用外接SPI Flash了)。
源程序下载:http://download.csdn.net/detail/mostone/6024943
OS:windows 2008 R2 standard (zh-cn)
IDE:Microsoft Visual Studio Express 2012 for Windows Desktop - Microsoft Visual C# 2012
两个点阵字体下载链接:
常用的几个字体库---ASC16、HZK16、HZK12,附HZK16的使用资料
16*16点阵中文字库BIN文件
先上几张图:
查看器有两个 Form,一个是主画面,一个是选择字体对话框。布局如上图,下面是两个源代码:
Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace HZK { public partial class Form1 : Form { System.IO.Stream pFontReadStream; string pFontFileName; int pPageNo = 0; Size pFontSize; Bitmap pBitmap; Graphics pGraphics; FormOpenFontDialog pDialog = null; static string[] FONT_SIZE_LIST = new string[] { "12x6", "12x8", "12x12", "16x8", "16x16", "24x24", "40x20", "40x40", "48x24", "48x48" }; public Form1() { InitializeComponent(); this.pBitmap = new Bitmap(930, 910); this.pGraphics = Graphics.FromImage(pBitmap); this.toolStripStatusLabel1.Visible = false; this.toolStripProgressBar1.Visible = false; this.comboBox1.Items.AddRange(FONT_SIZE_LIST.ToArray()); } public static string[] getFontSizeList() { return FONT_SIZE_LIST; } private Size getSize(string value) { return new Size(Int16.Parse(value.Substring(3)), Int16.Parse(value.Substring(0, 2))); } private void btnPickFont_Click(object sender, EventArgs e) { if (pDialog == null) pDialog = new FormOpenFontDialog(); if (pDialog.ShowDialog() != DialogResult.OK) return; pFontReadStream = pDialog.getFontFileStream(); pFontSize = this.getSize(pDialog.getFontSize()); pFontFileName = pDialog.getFontFileName(); redraw(); } private void redraw() { pPageNo = 0; drawPage(pPageNo); this.toolStripStatusLabel1.Text = String.Format("{0} Font size:{1}x{2}", pFontFileName, pFontSize.Height, pFontSize.Width); } private void drawPage(int pageNo) { if (pFontReadStream == null) return; const int space = 5; const int ox = 50; const int oy = 20; Point pt = new Point(ox, oy); pFontReadStream.Position = pageNo * 16 * 16 * (pFontSize.Width == 12 ? 16 : pFontSize.Width) * pFontSize.Height / 8; pGraphics.Clear(this.pictureBox1.BackColor); this.toolStripStatusLabel1.Visible = false; this.toolStripProgressBar1.Visible = true; List<byte> list = new List<byte>(); bool eof = false; int tmp; for (int row = 0; row < 16; row++) { pGraphics.DrawString((pageNo * 16 * 16 + row * 16).ToString("X4"), DefaultFont, Brushes.Black, new Point(10, oy + row * (space + pFontSize.Height))); for (int col = 0; col < 16; col++) { for (int i = 0; i < (pFontSize.Width == 12 ? 16 : pFontSize.Width) * pFontSize.Height / 8; i++) { tmp = pFontReadStream.ReadByte(); if (tmp == -1) { eof = true; break; } list.Add((byte)tmp); } if (eof) break; if (this.radioButton1.Checked) { drawFontAsRowScan(pt, pGraphics, list, pFontSize); } else { drawFontAsColumnScan(pt, pGraphics, list, pFontSize); } pt.X += space + pFontSize.Width; list.Clear(); this.toolStripProgressBar1.Value = Math.Min((row * 16 + col) / 16 * 16, 100); } if (eof) break; pt.Y += space + pFontSize.Height; pt.X = ox; } pictureBox1.Image = pBitmap; this.toolStripProgressBar1.Visible = false; this.toolStripStatusLabel1.Visible = true; } // draw one char private void drawFontAsRowScan(Point pt, Graphics graph, List<byte> list, Size fontSize) { Pen pen; int mask; int bytesPerLine = (int)Math.Ceiling((decimal)fontSize.Width / 8); List<byte>.Enumerator enm = list.GetEnumerator(); enm.MoveNext(); byte byteData = enm.Current; for (int row = 0; row < fontSize.Height; row++) { for (int bytes = 0; bytes < bytesPerLine; bytes++) { mask = 0x80; for (int bits = 0; bits < 8; bits++) { pen = ((byteData & mask) == mask ? Pens.Black : Pens.White); graph.DrawRectangle(pen, pt.X, pt.Y, 1, 1); mask = mask >> 1; pt.X += 1; if (bytes * 8 + bits == fontSize.Width - 1) break; } enm.MoveNext(); byteData = enm.Current; } pt.Y += 1; pt.X -= fontSize.Width; } } // draw one char private void drawFontAsColumnScan(Point pt, Graphics graph, List<byte> list, Size fontSize) { Pen pen; int mask; int bytesPerLine = (int)Math.Ceiling((decimal)fontSize.Width / 8); List<byte>.Enumerator enm = list.GetEnumerator(); enm.MoveNext(); byte byteData = enm.Current; for (int col = 0; col < fontSize.Width; col++) { for (int bytes = 0; bytes < bytesPerLine; bytes++) { mask = 0x80; for (int bits = 0; bits < 8; bits++) { pen = ((byteData & mask) == mask ? Pens.Black : Pens.White); graph.DrawRectangle(pen, pt.X, pt.Y, 1, 1); mask = mask >> 1; pt.Y += 1; if (bytes * 8 + bits == fontSize.Height - 1) break; } enm.MoveNext(); byteData = enm.Current; } pt.X += 1; pt.Y -= fontSize.Height; } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (pFontReadStream != null) { pFontReadStream.Close(); } } private void button1_Click(object sender, EventArgs e) { drawPage(++pPageNo); } private void button2_Click(object sender, EventArgs e) { if (pPageNo == 0) return; drawPage(--pPageNo); } private void button3_Click(object sender, EventArgs e) { if (pFontReadStream == null) return; if (this.saveFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; System.IO.Stream ss = this.saveFileDialog1.OpenFile(); System.IO.StreamWriter sw = new System.IO.StreamWriter(ss); pFontReadStream.Position = 0; int byt; int pos = 0; while (true) { byt = pFontReadStream.ReadByte(); if (byt == -1) break; pos++; if (pos == 32) { sw.WriteLine("0x" + byt.ToString("X2") + ","); pos = 0; } else { sw.Write("0x" + byt.ToString("X2") + ","); } } sw.Close(); MessageBox.Show("Font array export done."); } private void radioButton1_CheckedChanged(object sender, EventArgs e) { drawPage(pPageNo); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { this.pFontSize = getSize(this.comboBox1.SelectedItem.ToString()); redraw(); } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace HZK { public partial class FormOpenFontDialog : Form { string pFontSize = null; public FormOpenFontDialog() { InitializeComponent(); string[] fontSizeList = Form1.getFontSizeList(); string prevFontSize = null; Size radioSize = new Size(120, 30); int radioOriX = 25; Point radioLocation = new Point(radioOriX, 30); foreach (string fontSize in fontSizeList) { if (prevFontSize == null) { prevFontSize = fontSize.Substring(0, 2); } else if (fontSize.Substring(0, 2) != prevFontSize) { radioLocation.Y += radioSize.Height; radioLocation.X = radioOriX; prevFontSize = fontSize.Substring(0, 2); } RadioButton radio = new RadioButton(); radio.Text = fontSize; radio.Location = radioLocation; radio.CheckedChanged += new System.EventHandler(this.radio_CheckedChanged); this.groupBox1.Controls.Add(radio); radioLocation.X += radioSize.Width; } } private void btnPickFont_Click(object sender, EventArgs e) { if (this.openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; this.txtFontFile.Text = this.openFileDialog1.FileName; } private void button3_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string getFontFileName() { return this.txtFontFile.Text; } public System.IO.Stream getFontFileStream() { if (this.txtFontFile.Text.Length != 0) { return this.openFileDialog1.OpenFile(); } return null; } public string getFontSize() { return pFontSize; } private void button1_Click(object sender, EventArgs e) { if (this.txtFontFile.Text.Length == 0) { MessageBox.Show("Please select font file."); return; } if (pFontSize == null) { MessageBox.Show("Please select font type."); return; } this.DialogResult = DialogResult.OK; } private void radio_CheckedChanged(object sender, EventArgs e) { pFontSize = ((RadioButton)sender).Text; } } }