65.9K
CodeProject is changing. Read more.
Home

WPF: Transform PathGeometry data in mini-language

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

May 3, 2018

CPOL
viewsIcon

8326

Parse, scale and/or translate Path data to create new XAML data

Introduction

Instead of using a constant RenderTransform to transform a given PathGeometry at runtime, the following routine creates the desired XAML.
Basically it splits the data into commands (upper- or lowercase letters) and coordinates.
All coordinates are scaled, only absolute coordinates (preceeding uppercase letter) are translated.

using System;
using System.Globalization;
using System.Text;

public static string ScaleTranslatePath(string data, double scale = 1, double x = 0, double y = 0, int digits = 1)
{
    string format = "0." + new string('#', digits);

    StringBuilder sb = new StringBuilder(data.Length);

    if (data.StartsWith("F0") || data.StartsWith("F1"))
    {
        // StreamGeometry.FillRule
        sb.Append(data.Substring(0, 3));
        data = data.Substring(3);
    }

    string[] parts = data.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
    int i = 0;
    bool isAbsolute = false;

    foreach (string part in parts)
    {
        double value;
        if (part.Length == 1 && char.IsLetter(part, 0))
        {
            i = 0;
            isAbsolute = char.IsUpper(part, 0);
            sb.Append(part);
        }
        else if (double.TryParse(part, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out value))
        {
            value *= scale;

            if (isAbsolute)
            {
                if (i++ % 2 == 0)
                {
                    value += x;
                }
                else
                {
                    value += y;
                }
            }

            value = Math.Round(value, digits);
            sb.Append(value.ToString(format, CultureInfo.InvariantCulture));
        }

        sb.Append(' ');
    }

    return sb.ToString(0, sb.Length - 1);
}

MSDN: Path Markup Syntax