Я только что написал это FrameworkElement
, которое позволит получить геометрию текста рендера с контуром. На исследование ушло около 10 минут, а потом - 20 минут.
Использование:
<Grid>
<local:OutlineTextElement Text="Hello" />
</Grid>
Код:
public class OutlineTextElement : FrameworkElement
{
public FontFamily FontFamily { get; set; }
public FontWeight FontWeight { get; set; }
public FontStyle FontStyle { get; set; }
public int FontSize { get; set; }
public int Stroke { get; set; }
public SolidColorBrush Background { get; set; }
public SolidColorBrush Foreground { get; set; }
public SolidColorBrush BorderBrush { get; set; }
private Typeface Typeface;
private VisualCollection Visuals;
private Action RenderTextAction;
private DispatcherOperation CurrentDispatcherOperation;
private string text;
public string Text
{
get { return text; }
set
{
if (String.Equals(text, value, StringComparison.CurrentCulture))
return;
text = value;
QueueRenderText();
}
}
public OutlineTextElement()
{
Visuals = new VisualCollection(this);
FontFamily = new FontFamily("Century");
FontWeight = FontWeights.Bold;
FontStyle = FontStyles.Normal;
FontSize = 240;
Stroke = 4;
Typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal);
Foreground = Brushes.Black;
BorderBrush = Brushes.Gold;
RenderTextAction = () => { RenderText(); };
Loaded += (o, e) => { QueueRenderText(); };
}
private void QueueRenderText()
{
if (CurrentDispatcherOperation != null)
CurrentDispatcherOperation.Abort();
CurrentDispatcherOperation = Dispatcher.BeginInvoke(RenderTextAction, DispatcherPriority.Render, null);
CurrentDispatcherOperation.Aborted += (o, e) => { CurrentDispatcherOperation = null; };
CurrentDispatcherOperation.Completed += (o, e) => { CurrentDispatcherOperation = null; };
}
private void RenderText()
{
Visuals.Clear();
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
FormattedText ft = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Typeface, FontSize, Foreground);
Geometry geometry = ft.BuildGeometry(new Point(0.0, 0.0));
dc.DrawText(ft, new Point(0.0, 0.0));
dc.DrawGeometry(null, new Pen(BorderBrush, Stroke), geometry);
}
Visuals.Add(visual);
}
protected override Visual GetVisualChild(int index)
{
return Visuals[index];
}
protected override int VisualChildrenCount
{
get { return Visuals.Count; }
}
}