Replies: 1 comment
-
I received a helpful answer on Stack Overflow after placing a bounty on my question. For reference purposes, I would like to share it here. public void Draw(string text)
{
var imageSize = 300;
var fontSize = 18;
var border = 10;
var color = Color.ParseHex("#808080");
FontFamily family = SystemFonts.Get("Arial");
Font font = new(family, fontSize);
var radius = imageSize / 2;
var center = new PointF(radius, radius);
var img = Image<Rgba32>.Load(@"C:\tmp\comet.png");
img.Mutate(o => o.Resize(new Size(imageSize, imageSize)));
var topSegment = new ArcLineSegment(center, new SizeF(radius - border, radius - border), 0, -220, 260);
PathBuilder pathBuilder = new PathBuilder();
pathBuilder.AddSegment(topSegment);
var bottomSegment = new ArcLineSegment(center, new SizeF(radius - fontSize / 2 - border, radius - fontSize / 2 - border), 0, -220, -100);
// Find the smallest curve encompassing the whole text
var textSweepAngle = FindLowestSweepAngle(text, font, new SizeF(radius - fontSize / 2 - border, radius - fontSize / 2 - border));
var fullSweepAngle = 100;
var gapSweepAngle = (fullSweepAngle - textSweepAngle) / 2;
var textStartAngle = -220 - gapSweepAngle;
var textSegment = new ArcLineSegment(center, new SizeF(radius - fontSize / 2 - border, radius - fontSize / 2 - border), 0, textStartAngle, -textSweepAngle);
IPath textShape = new Polygon(textSegment);
TextOptions textOptions = new(font)
{
WrappingLength = textShape.ComputeLength(),
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
TextAlignment = TextAlignment.Start,
TextDirection = TextDirection.LeftToRight
};
DrawingOptions options = new()
{
GraphicsOptions = new()
{
ColorBlendingMode = PixelColorBlendingMode.Multiply
}
};
IPen pen = Pens.Solid(color, 1);
img.Mutate(x => x.Draw(color, 2, pathBuilder.Build()));
img.Mutate(x => x.Draw(color, 2, new PathBuilder().AddSegment(bottomSegment).Build()));
IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, textShape, textOptions);
img.Mutate(i => i.Fill(color, glyphs));
string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine("test.png")));
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
img.Save(fullPath);
Console.WriteLine($"Saved to {fullPath}");
}
private float FindLowestSweepAngle(string text, Font font, SizeF radius)
{
var low = 0.1f;
var high = 359.9f;
var step = 0.1f;
while (low < high)
{
var mid = (low + high) / 2;
var arcLineSegment = new ArcLineSegment(PointF.Empty, radius, 0, 0, mid);
var polygon = new Polygon(arcLineSegment);
TextOptions textOptions = new(font)
{
WrappingLength = polygon.ComputeLength(),
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
TextAlignment = TextAlignment.Start,
TextDirection = TextDirection.LeftToRight
};
try
{
TextBuilder.GenerateGlyphs(text, polygon, textOptions);
high = mid - step; // Curve is too big. Keep finding a smaller one
}
catch // InvalidOperationException: Should always reach a point along the path
{
low = mid + step; // Curve is too small to hold the whole text
}
}
return low;
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm trying to replicate this: (drawing circle and text in the lower arc)

With this code:
I get to this result:
My questions are:
GenerateGlyphs
will fail with'Should always reach a point along the path.'
. Is there a way to scale the text size to fit the arc automatically if the text is too long?EDIT: I experimented with different segments, I have the same issue with a simpler line segment:
Similarly

TextAligment
has no effect and havingHorizontalAligment.Center
will cause the text to be aligned in the middle of the segment start point:What is also strange is that the
textShape.ComputeLength()
returns 400 in the above example, whereas the segment is only 200 long.Thanks a lot
Beta Was this translation helpful? Give feedback.
All reactions