字距和字符间距是不同的,如果您想完全控制代码打印的内容,您可能需要同时实现两者。
让我们先看一个示例输出:
图一显示直接输出,额外字符间距为 1 像素,无字距调整。
图像 2应用了一些字距调整,但仅适用于三个字距调整对。
我还试图通过绘制字符文本测量的结果来使事情更清楚。还有一个平铺的 1 像素光栅作为面板 BackgroundImage。(为了更好地查看它,您可能需要下载 png 文件!)
private void panel2_Paint(object sender, PaintEventArgs e)
{
string fullText = "Text;1/2' LTA";
StringFormat strgfmt = StringFormat.GenericTypographic;
Font font = new Font("Times", 60f, FontStyle.Regular);
float x = 0f;
using (SolidBrush brush = new SolidBrush(Color.FromArgb(127, 0, 127, 127)))
{
for (int i = 0; i < fullText.Length; i++)
{
string text = fullText.Substring(i, 1);
SizeF sf = e.Graphics.MeasureString(text, font, 9999, strgfmt );
e.Graphics.FillRectangle(brush, new RectangleF(new PointF(x, 0f), sf));
e.Graphics.DrawString(text, font, Brushes.Black, x, 0, strgfmt );
x += sf.Width + 1; // character spacing = +1
//if (i < fullText.Length - 1) doKerning(fullText.Substring(i, 2), ref x);
}
}
}
void doKerning(string c12, ref float x)
{
if (smallKerningTable.ContainsKey(c12)) x -= smallKerningTable[c12];
}
Dictionary<string, float> smallKerningTable = new Dictionary<string, float>();
void initKerningTable()
{
smallKerningTable.Add("Te", 7f);
smallKerningTable.Add("LT", 8f);
smallKerningTable.Add("TA", 11f);
//..
}
这是创建背景的方式:
public Form1()
{
InitializeComponent();
Bitmap bmpCheck2 = new Bitmap(2, 2);
bmpCheck2.SetPixel(0, 0, Color.FromArgb(127, 127, 127, 0));
panel2.BackgroundImage = bmpCheck2;
panel2.BackgroundImageLayout = ImageLayout.Tile;
//..
}
如果您想使用字距调整,您将需要构建一个更长的字距调整表。
在现实生活中,排版师和字体设计师手动进行,仔细查看字形,调整字距,直到看起来非常好。
这是相当昂贵的,仍然不包括字体混合。
所以你可能想要
- 毕竟不使用字距调整。确保使用该
StringFormat.GenericTypographic
选项来测量和绘制琴弦!
- 为一些特别有问题的字符创建一个小的字距调整表,例如“L”、“T”、“W”、“V”和“A”。
- 编写代码为您需要的所有对创建一个完整的字距调整表,或者..
- 对于所有对
要编写代码来创建字距调整表,您将:
- 为每个字符创建一个位图
- 遍历所有对和
- 将第二个位图向左移动,直到一些不透明/黑色像素发生碰撞。
- 移动不应超过宽度的一半,否则距离应重置为 0,因为某些字符对根本不会发生冲突并且不应该有任何字距调整,例如:'^_' 或 '.- '
如果您想混合字体和/或字体样式,则必须扩展字距调整表的键以包含字符具有的两种相应字体和样式的某些 ID。