65.9K
CodeProject is changing. Read more.
Home

WPF Text Outline Font

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (13 votes)

Jun 14, 2016

CPOL

2 min read

viewsIcon

27611

downloadIcon

931

This presents as control inherited from the Shape control for displaying an outline font.

Introduction

I needed an outline font for an application I was working on. I found a number of solutions, but the all seemed to have issues. I managed to take one solution (Outlined Text in WPF - julmar.com[^]) and heavily modify it to do a better job with sizing so that could use the HorizontalAlignment without issues. This solution still has issues with VerticalAlignment, and had to do some tweaks on the display to ensure that numbers were properly aligned with words in different controls because the words had descenders, and changed the spacing.

The Design

There are a number different controls to inherit from to create a Control for outline text. I ended up inheriting from the Shape class for no particular reason. However, FormattedText can be used directly with the Geometry method of the Shape class. Have also seen the Canvas used as the inherited class. The class has a number of DependencyProperty definitions, including Origin, FontSize, FontWeight, FontFamily, Text, FontStretch. The rest of the class is as follows:

  protected override Geometry DefiningGeometry => _textGeometry ?? Geometry.Empty;

  private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
		=> ((TextPath)d).CreateTextGeometry();

  private void CreateTextGeometry()
  {
   var formattedText = new FormattedText(Text, Thread.CurrentThread.CurrentUICulture, 
	FlowDirection.LeftToRight, new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), 
	FontSize, Brushes.Black);
   _textGeometry = formattedText.BuildGeometry(Origin);
  }

  protected override Size MeasureOverride(Size availableSize)
  {
   if (_textGeometry == null) CreateTextGeometry();
   if (_textGeometry.Bounds == Rect.Empty)
    return new Size(0, 0);
   // return the desired size
   return new Size(Math.Min(availableSize.Width, _textGeometry.Bounds.Width), 
	Math.Min(availableSize.Height, _textGeometry.Bounds.Height));
  }

The major addition I did for this class from the one I found was added the MeasureOverride. This is what allows the automatic sizing of WPF to work, and ensures that the alignment properties work. The XAML to use this class is as follows:

  <local:TextPath Margin="10"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Center"
                  Fill="Yellow"
                  Stroke="Black"
                  StrokeThickness="1.5"
                  FontFamily="Ariel"
                  FontSize="32"
                  FontWeight="Bold"
                  Text="This is a Test of Outline Text" />

Conclusion

I am sure that this class could use some improvement, and would love input. As I stated above, there are still issues with the Vertical alignment. Since I have found so many questions and answers about creating and outline font, providing a capability of providing an outline font is one of many oversights of Microsoft in delivering the WPF framework, which is the more recent of two frameworks to use to create desktop applications for Windows, both of which are really no longer supported.