-
Notifications
You must be signed in to change notification settings - Fork 0
/
Convert-Shape.ps1
193 lines (160 loc) · 6.27 KB
/
Convert-Shape.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<#
.SYNOPSIS
Converts generic XAML files to Paint.NET shape XAML files.
.DESCRIPTION
Parameter aliases:
-i -in <path> Input file or folder
-o -out <path> Output folder
-p -pretty If present, output files will be human-readable
Display name of each shape will be set according to filename.
If you set output to the same folder where input file located,
then suffix "_converted" will be added to output file name (not display name).
.PARAMETER inputPath
Input file or folder to be converted.
.PARAMETER outDir
Folder where converted files should be placed.
Folder will be created in case it isn't exist already.
.PARAMETER prettyPrint
If present, output XAML files will be formatted for readability and further editing.
Otherwise there will be no new lines and indentation.
.EXAMPLE
./_convert.ps1 .\shape_sources
Convert all files in .\shape_sources folder (non-recursive).
Default output folder is .\output
.EXAMPLE
./_convert.ps1 -in .\shape_sources -pretty
Convert all files in .\shape_sources folder (non-recursive).
Default output folder is .\output
Output files formatted for readability and further editing.
.EXAMPLE
./_convert.ps1 .\some_folder\example.xaml
Convert single file.
Converted file will be saved into .\output folder by default.
.EXAMPLE
./_convert.ps1 .\shape_sources .\output
Convert all files in .\shape_sources folder (non-recursive)
and put resulting files into .\output folder.
.EXAMPLE
./_convert.ps1 -i .\shape_sources -o .\output -p
Parameters can be unnamed (ordered) or named with full names
or one letter aliases like in this example.
.NOTES
Put some notes here.
.LINK
http://mxii.eu.org/project/paintdotnetstuff - This script and other my stuff for Paint.NET
.LINK
http://forums.getpaint.net/index.php?/topic/32101-h - How to make custom shapes for Paint.NET
#>
Param (
[Parameter(Mandatory, HelpMessage="Input file or folder to be converted.")]
[ValidateScript({Test-Path $_})]
[Alias("i","in")][string]$inputPath,
[Alias("o","out")][string]$outDir = ".\output",
[Alias("p","pretty")][switch]$prettyPrint
)
#$DebugPreference = "Continue"
Set-StrictMode -Version Latest
# Constants
$extendedFileNameSuffix = "_converted"
function Convert-Shapes {
if(-Not (Test-Path $outDir)) { # make output folder if needed
New-Item -ItemType directory -Path $outDir | Out-Null
}
$inputItem = Get-Item -Path $inputPath
$outputFolderItem = Get-Item -Path $outDir
if (Test-Path $inputPath -PathType Container) # folder
{
Convert-Folder $inputItem $outputFolderItem
}
else # single file
{
Convert-SingleFile $inputItem $outputFolderItem
}
Write-Output " Finished."
Write-Output ""
}
function Convert-Folder($inputFolder, $outputFolder) {
$fileList = Get-ChildItem "$($inputFolder.FullName)\" -Filter *.xaml -File
Write-Output " $(Split-Path $inputFolder -leaf)"
Write-Output " $($fileList.Count) files to convert."
$fileList | %{ Convert-SingleFile $_ $outputFolder }
}
function Convert-SingleFile($inputFile, $outputFolder) {
Write-Debug "$($inputFile.FullName)"
$conversionResult = Convert-Item $inputFile
$xml = $conversionResult["xml"]
$attrBased = $conversionResult["attributeBased"]
$outputFilePath = Make-OutputPath $inputFile $outputFolder $false
if($inputFile.FullName -eq $outputFilePath) # avoid overwriting of input file
{
$outputFilePath = Make-OutputPath $inputFile $outputFolder $true
}
Save-ShapeXml $xml $outputFilePath $prettyPrint.IsPresent $attrBased
}
function Make-OutputPath($item, $outputFolder, $isExtendedName) {
Return "$outputFolder\$($item.BaseName)$(if($isExtendedName){$extendedFileNameSuffix}).xaml"
}
function Convert-Item($fileItem) {
$shapeName = $fileItem.BaseName
$xdoc = [xml] (Get-Content $fileItem.FullName)
$ns = New-Object System.Xml.XmlNamespaceManager($xdoc.NameTable)
$ns.AddNamespace("ns", $xdoc.DocumentElement.NamespaceURI)
$xPathNode = $xdoc.SelectSingleNode("//ns:Path", $ns)
if($xPathNode.HasAttribute("Data"))
{
Return @{
"xml" = Make-AttributeShape $xPathNode.Data $shapeName;
"attributeBased" = $true
}
}
else
{
Return @{
"xml" = Make-NodeShape $xPathNode.'Path.Data'.InnerXml $shapeName;
"attributeBased" = $false
}
}
}
function Make-AttributeShape([string]$stringData, [string]$shapeName) {
$doc = Get-ShapeTemplate
$doc.SimpleGeometryShape.SetAttribute("DisplayName", $shapeName)
$doc.SimpleGeometryShape.SetAttribute("Geometry", $stringData)
Return $doc
}
function Make-NodeShape($xml, [string]$shapeName) {
$doc = Get-ShapeTemplate
$doc.SimpleGeometryShape.SetAttribute("DisplayName", $shapeName)
$doc.SimpleGeometryShape.InnerXml = $xml
Return $doc
}
function Get-ShapeTemplate {
Return [xml]"<ps:SimpleGeometryShape xmlns=""clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework""
xmlns:ps=""clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"" />"
}
function Save-ShapeXml($xmldoc, $outputPath, $isPrettyPrint, $isAttrNewLine) {
# Removing namespace which was added when xml fragmant was grafted from one file to another.
$outstr = $xmldoc.OuterXml.Replace(" xmlns=`"http://schemas.microsoft.com/winfx/2006/xaml/presentation`"", "")
if($isPrettyPrint)
{
$outstr = XmlPrettyPrint $outstr $isAttrNewLine
}
# Using XmlWriter in XmlPrettyPrint function messes the encoding.
# Making utf8 without BOM explicitly here.
$utf8noBOM = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($outputPath, $outstr, $utf8noBOM)
}
function XmlPrettyPrint([string]$xmlstr, $isAttrNewLine) {
$sw = New-Object System.IO.StringWriter
$settings = New-Object System.Xml.XmlWriterSettings
$settings.CloseOutput = $true
$settings.Indent = $true
$settings.NewLineOnAttributes = $isAttrNewLine
$settings.OmitXmlDeclaration = $true
$writer = [System.Xml.XmlWriter]::Create($sw, $settings)
$xmldoc = New-Object system.xml.xmlDataDocument
$xmldoc.LoadXml($xmlstr)
$xmldoc.WriteContentTo($writer)
$writer.Flush()
Return $sw.ToString()
}
Convert-Shapes