// 使用 xaml 资源
// <FontFamily x:Key="ZiYuFangFuhHeiTi">../Resource/Fonts/#字语坊腹黑体</FontFamily> // 嵌入字体,编译为 Resource, 名称前有 #
// var fontFamily = application.FindResource("ZiYuFangFuhHeiTi") as FontFamily;
var fontFamily = new FontFamily("../Resource/Fonts/#字语坊腹黑体");
Debug.Assert(fontFamily != null);
var typeface = GeometryDataUtility.CreateTypeface(fontFamily!);
// var dpiScale = DpiHelper.GetScale(Application.Current.MainWindow);
var geometry = GeometryDataUtility.ConvertStringToCombinedPath("质量是制造出来的", typeface, 72);
var bounds = geometry.Bounds;
testOutputHelper.WriteLine($"路径尺寸: {bounds}");
var len = GeometryDataUtility.GetGeoetryLength(geometry);
testOutputHelper.WriteLine($"路径长度: {len}");
var pathData = GeometryDataUtility.GetPathDataXml(geometry);
testOutputHelper.WriteLine($"路径 xml 表示: {pathData}");
public static class GeometryDataUtility
{
// 返回文字的 Geometry
public static Geometry ConvertStringToCombinedPath(string text, Typeface typeface, double fontSize = 32, double pixelsPerDip = 1)
{
// 下面可以自定义字边距
var geometryGroup = new GeometryGroup();
double currentX = 0;
foreach (var c in text)
{
// 创建单个字符的 FormattedText
var formattedText = new FormattedText(
c.ToString(),
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
typeface,
fontSize,
Brushes.Black, pixelsPerDip);
// 获取字符宽度用于计算下一个字符位置
var charWidth = formattedText.WidthIncludingTrailingWhitespace;
// 构建字符的 Geometry,并平移到正确位置
var geometry = formattedText.BuildGeometry(new Point(currentX, 0));
if (geometry == null)
{
continue;
}
geometryGroup.Children.Add(geometry);
// 更新下一个字符的起始位置
currentX += charWidth - 24;
}
return geometryGroup;
}
public static Typeface CreateTypeface(Control control)
{
return new Typeface(control.FontFamily, control.FontStyle, control.FontWeight, control.FontStretch);
}
public static Typeface CreateTypeface(FontFamily fontFamily)
{
return new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
}
// 计算路径长度
public static double GetGeoetryLength(Geometry geometry)
{
var pathGeometry = geometry.GetFlattenedPathGeometry();
// 取线段的 1% 位置时的坐标
pathGeometry.GetPointAtFractionLength(0d, out var firstPoint, out _);
pathGeometry.GetPointAtFractionLength(0.01, out var point, out _);
// 取起点至 1% 坐标向量的长度,然后再乘以 100 倍,近似得到线段的总长度
var len = (firstPoint - point).Length * 100;
return len;
}
// 返回 pathData 的 xml 表示
public static string GetPathDataXml(Geometry geometry)
{
var pathMarkup = XamlWriter.Save(geometry);
return pathMarkup;
}
}