Search code examples
xmlxamlpretty-print

Need to "Prettify" Xaml: Convert a long PathGeometry "Figures" attribute string to XML syntax


I have a whole lot of icons that I am using in my application. I've got them in a XAML Resource dictionary at PathGeometry objects with the figures specified in attribute syntax, like this:

<PathGeometry x:Key="RunPathGeometry" 
              Figures="M56.11 46.17 69.2 33.09a25.29 25.29 0 1 0 4.41 27H85.16l.1 0q-.25.91-.57 1.8A36.32 36.32 0 1 1 77 25.3l8.92-8.92V46.17Z" 
              FillRule="NonZero"
              />

Now this works just fine but some of these icons are so complicated and the attribute strings so long that I have -- literally -- over 30,000 columns of text.

I would very much prefer to have these expressed in property syntax, if only because it would give me a ton of lines instead of a columns. Lines I can live with (and there would certainly be a lot less then 30,000...)

Is there some simple method/converter anyone know of that would do this for me? Perhaps where I could paste in the PathGeometry in one format and get it out in another?

Skimming the docs it looks like I could likely write one myself with XamlReader/XamlWriter but I'd rather not reinvent the wheel and burn all the cycles to do this if someone has already...

Edited -- since someone asked, What I mean by "Property" syntax is where the figures are expressed in closed XML tags rather than in attributes. something like this example below (It's actually for a simple triangle example but more complicated shapes can be expressed as well.)

<Path Stroke="Black" StrokeThickness="1">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure IsClosed="True" StartPoint="10,100">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <LineSegment Point="100,100" />
                                <LineSegment Point="100,50" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>

Solution

  • We've got a bunch of these in a resource dictionary and we've been very happy with it:

    <PathGeometry x:Key="SearchGlyphPathGeometry" x:Shared="True" FillRule="EvenOdd">
        <PathGeometry.Figures>
            M 25,13
            A 12,12, 0,1,1, 13,25
            A 12,12, 0,0,1, 25,13
            Z
            M 35.8,41.8
            A 20,20, 0,0,1, 5,25
            A 20,20, 0,1,1, 41.8,35.8
            L 57,51
            L 51,57
            Z
        </PathGeometry.Figures>
    </PathGeometry>
    

    Use like so:

    <Path Data="{StaticResource SearchGlyphPathGeometry}" Fill="DeepSkyBlue" />
    

    It would be simple enough to use perl or sed to insert linebreaks in front of every alpha character in a path string. Or C#:

    var re = new Regex("([a-z])", RegexOptions.IgnoreCase);
    var s = re.Replace(PathGeometryText, "\n\t\t\t$1");
    

    You could write code to recursively search your project directory for XAML files, look for PathGeometry elements, transform the Figures attribute value with the above regex, remove the attribute, and add a child element instead:

    <PathGeometry x:Key="RunPathGeometry" FillRule="NonZero">
        <PathGeometry.Figures>
    
            M56.11 46.17 69.2 33.09
            a25.29 25.29 0 1 0 4.41 27
            H85.16
            l.1 0
            q-.25.91-.57 1.8
            A36.32 36.32 0 1 1 77 25.3
            l8.92-8.92
            V46.17
            Z 
        </PathGeometry.Figures>
    </PathGeometry>
    

    I'd also do something about that mildly annoying orphan newline the regex leaves in front of the text.

    For your original idea, you could write some trivial C# code to instantiate PathGeometry instances from your strings and serialize them as XAML, but the above seems to me to be at least as readable, and less work besides.