在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
两个点阵字体下载链接:
先上几张图:
查看器有两个 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();
}
}
}
FormOpenFontDialog.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 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;
}
}
}