如何将曲线文本渲染为位图?

我目前正在动态创建一个位图,并使用位图中的图形对象在其上绘制一个字符串,如下所示:

System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(bmp); graph.DrawString(text, font, brush, new System.Drawing.Point(0, 0)); 

这将返回一个矩形位图,其中字符串从左到右直接写入。 我也希望能够画出彩虹形状的弦乐。 我怎样才能做到这一点?

我最近遇到了这个问题(我正在渲染用于打印到CD上的文本),所以这是我的解决方案:

 private void DrawCurvedText(Graphics graphics, string text, Point centre, float distanceFromCentreToBaseOfText, float radiansToTextCentre, Font font, Brush brush) { // Circumference for use later var circleCircumference = (float)(Math.PI * 2 * distanceFromCentreToBaseOfText); // Get the width of each character var characterWidths = GetCharacterWidths(graphics, text, font).ToArray(); // The overall height of the string var characterHeight = graphics.MeasureString(text, font).Height; var textLength = characterWidths.Sum(); // The string length above is the arc length we'll use for rendering the string. Work out the starting angle required to // centre the text across the radiansToTextCentre. float fractionOfCircumference = textLength / circleCircumference; float currentCharacterRadians = radiansToTextCentre + (float)(Math.PI * fractionOfCircumference); for (int characterIndex = 0; characterIndex < text.Length; characterIndex++) { char @char = text[characterIndex]; // Polar to cartesian float x = (float)(distanceFromCentreToBaseOfText * Math.Sin(currentCharacterRadians)); float y = -(float)(distanceFromCentreToBaseOfText * Math.Cos(currentCharacterRadians)); using (GraphicsPath characterPath = new GraphicsPath()) { characterPath.AddString(@char.ToString(), font.FontFamily, (int)font.Style, font.Size, Point.Empty, StringFormat.GenericTypographic); var pathBounds = characterPath.GetBounds(); // Transformation matrix to move the character to the correct location. // Note that all actions on the Matrix class are prepended, so we apply them in reverse. var transform = new Matrix(); // Translate to the final position transform.Translate(centre.X + x, centre.Y + y); // Rotate the character var rotationAngleDegrees = currentCharacterRadians * 180F / (float)Math.PI - 180F; transform.Rotate(rotationAngleDegrees); // Translate the character so the centre of its base is over the origin transform.Translate(-pathBounds.Width / 2F, -characterHeight); characterPath.Transform(transform); // Draw the character graphics.FillPath(brush, characterPath); } if (characterIndex != text.Length - 1) { // Move "currentCharacterRadians" on to the next character var distanceToNextChar = (characterWidths[characterIndex] + characterWidths[characterIndex + 1]) / 2F; float charFractionOfCircumference = distanceToNextChar / circleCircumference; currentCharacterRadians -= charFractionOfCircumference * (float)(2F * Math.PI); } } } private IEnumerable GetCharacterWidths(Graphics graphics, string text, Font font) { // The length of a space. Necessary because a space measured using StringFormat.GenericTypographic has no width. // We can't use StringFormat.GenericDefault for the characters themselves, as it adds unwanted spacing. var spaceLength = graphics.MeasureString(" ", font, Point.Empty, StringFormat.GenericDefault).Width; return text.Select(c => c == ' ' ? spaceLength : graphics.MeasureString(c.ToString(), font, Point.Empty, StringFormat.GenericTypographic).Width); } 

程序输出中弯曲文本的屏幕截图

我认为唯一的方法是单独渲染每个角色并使用

 Graphics.RotateTransform 

旋转文本。 您需要自己计算旋转角度和渲染偏移量。 你可以使用

 Graphics.MeasureCharacterRanges 

获得每个角色的大小。

不幸的是,在GDI +中没有办法将字符串附加到路径上(这就是你要寻找的)。

所以这样做的唯一方法就是“手工”。 这意味着将字符串拆分为字符并根据您自己的路径计算放置它们。

除非你想在这方面投入大量的工作,否则你应该尝试找到一个库(可能完成GDI +替换)来做到这一点或放弃你的彩虹。

使用WPF,您可以在路径上呈现文本( 请参阅howto的链接 )