wpf Geometry 一些辅助函数

        // 使用 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;
    }

}
上一篇
下一篇