Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create multiple strokes on text in WPF?

Tags:

c#

wpf

I am trying to create text that looks like this in WPF:

sample text

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?

like image 251
BradleyDotNET Avatar asked Dec 23 '14 18:12

BradleyDotNET


1 Answers

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.

like image 84
BradleyDotNET Avatar answered Sep 20 '22 07:09

BradleyDotNET