I am trying to create text that looks like this in WPF:
Notice that it is yellow text, with a black stroke, then a yellow stroke, then another (very thin) black stroke. Now, I can create a single stroke with little difficult by following How to: Create Outlined Text. Note that the properties not shown are all DP's of the containing control.
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
// Draw the outline based on the properties that are set.
drawingContext.DrawGeometry(Fill,
new System.Windows.Media.Pen(Stroke, StrokeThickness),
_textGeometry);
}
/// <summary>
/// Create the outline geometry based on the formatted text.
/// </summary>
public void CreateText()
{
System.Windows.FontStyle fontStyle = FontStyles.Normal;
FontWeight fontWeight = FontWeights.Medium;
if (Bold == true) fontWeight = FontWeights.Bold;
if (Italic == true) fontStyle = FontStyles.Italic;
// Create the formatted text based on the properties set.
FormattedText formattedText = new FormattedText(
Text,
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(
Font,
fontStyle,
fontWeight,
FontStretches.Normal),
FontSize,
System.Windows.Media.Brushes.Black
);
// Build the geometry object that represents the text.
_textGeometry = formattedText.BuildGeometry(new System.Windows.Point(0, 0));
}
So my question is, how do I take that and add another (or several other) stroke(s) to it?
One method would be to combine the stroke geometry with the initial geometry, then stroke that for the second stroke.
Luckily, .NET proves Geometry.GetWidenedPathGeometry
for getting the stroke geometry. You can then use Geometry.Combine
to combine the two:
_combinedGeometry = Geometry.Combine(_textGeometry,
_textGeometry.GetWidenedPathGeometry(new Pen(Stroke, StrokeThickness * 2)),
GeometryCombineMode.Union, null);
Note the StrokeThickness * 2
. You need this because WPF draws a center stroke, and without it, the second stroke will at least partially (if not fully) cover up the first one. Then draw as before, with null
for Fill:
drawingContext.DrawGeometry(null,
new System.Windows.Media.Pen(SecondaryStroke, SecondaryStrokeThickness),
_combinedGeometry);
You can repeat this for additional strokes, or use a collection with a loop.
Warning: GetWidenedPathGeometry
will not always return a "perfect" stroke based on the font you are using, the size of the font, and the size of the stroke. You may have to play around with it a bit in order to not have any artifacts.
Workaround for above: If possible, increase the font size. It increases the distance between pieces of stroke, reducing the likelihood that the algorithm will "bridge" the two pieces, or create other artifacts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With