# 问题描述

需要绘制文本,字体 字号均需要自定义,限定矩形区域绘制,也就是说需要有自动换行,而且前两段文本需要不同颜色

# 实现思路

单独对每个字符进行手动绘制,循环文本列表,手动维护当前绘制坐标。由于是手动绘制每个字符,所以每个字符的颜色和大小都可进行控制。
自动换行也同理,检测 当前坐标的 X + 字符宽度 是否大于某个值.

# 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public static Bitmap GenTextPic(string oldText, string newText)
{
oldText = " " + oldText;
oldText = oldText.Replace("\\n", "\n").Replace("\n", "\n ");
newText = newText.Replace("\\n", "\n").Replace("\n", "\n ");
int padding = 20, width = MainSave.PicWidth;
Font font = new Font(MainSave.Font, 16, FontStyle.Regular);
int maxWidth = width - padding * 2, charGap = -8, maxHeight = 0;
using (Bitmap Result = new Bitmap(width, 30000))
{
using (Graphics g = Graphics.FromImage(Result))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.FillRectangle(Brushes.White, new RectangleF(0, 0, width, 30000));
PointF nowPoint = new PointF(padding, padding);
float maxCharWidth = 0;
foreach (var item in oldText)
{
DrawString(g, item, Brushes.Black, ref nowPoint, font, padding, charGap, ref maxCharWidth, maxWidth, out float charHeight);
}
foreach (var item in newText)
{
DrawString(g, item, Brushes.Red, ref nowPoint, font, padding, charGap, ref maxCharWidth, maxWidth, out float charHeight);
maxHeight = (int)(nowPoint.Y + charHeight + padding);
}
}
Bitmap tmp = new Bitmap(width, maxHeight);
using (Graphics g = Graphics.FromImage(tmp))
g.DrawImageUnscaled(Result, new Point(0, 0));
return tmp;
}
}

public static void DrawString(Graphics g, char text, Brush color, ref PointF point, Font font, int padding, int charGap, ref float maxCharWidth, int maxWidth, out float charHeight)
{
var charSize = g.MeasureString(text.ToString(), font);
charHeight = charSize.Height;
if (text == '\n')
{
point.X = padding;
point.Y += charSize.Height + 2;
return;
}
if (charSize.Width < -charGap)
charSize.Width = maxCharWidth > 0 ? maxCharWidth : (-charGap) * 3;
maxCharWidth = Math.Max(maxCharWidth, charSize.Width);
g.DrawString(text.ToString(), font, color, point);
WrapTest(maxWidth, padding, charGap, charSize, ref point);
}
public static void WrapTest(int maxWidth, int padding, int charGap, SizeF charSize, ref PointF point)
{
if (point.X + charSize.Width >= maxWidth)
{
point.X = padding;
point.Y += charSize.Height + 2;
}
else
{
point.X += charSize.Width + charGap;
}
}

上述代码对两段文本进行了绘制,前一段是黑色,后一段是红色。并且自定义了字符间距以及行间距,对空格以及换行符进行了特殊的处理,空格直接当做一个汉字处理,换行符则是直接触发一次换行坐标变换.

# 测试效果还行的参数

参数名称
emSize16
charGap-8
padding20
FontStyleRgeular

# 最终效果

Result