Skip to content

Commit 6087a7b

Browse files
committed
refactoring, cleanup and bugfixes (#14)
1 parent 5e0e6d4 commit 6087a7b

25 files changed

+3332
-1545
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,9 @@ ModelManifest.xml
244244
# FAKE - F# Make
245245
.fake/
246246
/SvgFileType/*.bak
247+
/SvgFileType/Program.cs
248+
/SVGFileTypePlugin_setup.exe
249+
/SvgFileTypePlugin.zip
250+
/setup.nsi
251+
/CreateZippedRelease.bat
252+
/header.bmp

COPYING

Lines changed: 829 additions & 13 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,49 @@
1-
SvgFileType
2-
===========
1+
# ![W3C SVG Logo](https://www.w3.org/Icons/SVG/svg-logo-v.png) Scalable Vector Graphics (SVG) Plugin for Paint.NET
2+
33
[![](https://img.shields.io/github/release-pre/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET.svg?style=flat)](https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/releases)
44
[![](https://img.shields.io/github/downloads/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/total.svg?style=flat)](https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/releases)
55

6-
**Please check the [Releases](https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/releases) section for binary download.**
7-
8-
**Please note:** The binary forms that you can get from the releases section are under the LGPL terms since they contain code from
9-
[Fizzler: .NET CSS Selector Engine](https://github.com/atifaziz/Fizzler) project.
10-
116
This is a Paint.NET filetype plugin for loading SVG (Scalable Vector Graphics) and its compressed variant SVGZ files.
127
SVG elements can be rendered as a flat image file or each on a separate layer.
138

149
The plugin is a tiny wrapper around the [SVG.NET Library](https://github.com/vvvv/SVG) which does the actual SVG reading.
1510

16-
Tested on paint.net 4.2.16 stable & 4.3 alpha (4.300.7881.3082) releases.
11+
Tested on Paint.NET 4.2.16 & 4.3 Beta Build 7929.
12+
13+
### Download links
14+
15+
Here are the download links for latest release:
16+
17+
<table>
18+
<tr>
19+
<th>Installer</th>
20+
<th>Manual Installation</th>
21+
</tr>
22+
<tr>
23+
<td><a href="https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/releases/latest/download/SvgFileType_setup.exe">SvgFileTypePlugin_setup.exe</a> (399 KiB)</td>
24+
<td><a href="https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET/releases/latest/download/SvgFileType.zip">SvgFileTypePlugin.zip</a> (274 KiB)</td>
25+
</tr>
26+
</table>
27+
28+
### How to install
29+
30+
&#x1F534; **Note: Before install make sure you don't have any other file type plugin installed handling the same file types as this plugin.**
1731

18-
To install the plugin perform the following steps:
19-
* Put the DLL in the `<Paint.NET>\FileTypes` directory (default location is `C:\Program Files\paint.net\FileTypes`)
20-
* For the [Windows Store version of Paint.NET](https://www.microsoft.com/store/apps/9NBHCS1LX4R0), put the DLL in the `<Documents>\paint.net App Files\FileTypes` directory
21-
* Restart Paint.NET if you have it open
32+
To auto install (recommended) the plugin perform the following steps:
33+
* Download and run `SvgFileTypePlugin_setup.exe`
34+
* Follow the steps of the setup wizard.
35+
36+
To manually install the plugin perform the following steps:
37+
* Download and extract `SvgFileTypePlugin.zip`
38+
* If you're using Paint.NET 4.3 or later:
39+
* If you're using Classic version of Paint.NET:
40+
* Create a new folder named `SvgFileTypePlugin` in the `<Paint.NET>\FileTypes` directory (default location is `C:\Program Files\paint.net\FileTypes`).
41+
* If you're using [Microsoft Store version of Paint.NET](https://www.microsoft.com/store/apps/9NBHCS1LX4R0):
42+
* Create a new folder named `SvgFileTypePlugin` in the `<Documents>\paint.net App Files\FileTypes` directory.
43+
* Put the extracted files in this newly created folder.
44+
* If you're using Paint.NET 4.2:
45+
* If you're using Classic version of Paint.NET:
46+
* Put the extracted files in the `<Paint.NET>\FileTypes` directory (default location is `C:\Program Files\paint.net\FileTypes`).
47+
* If you're using [Microsoft Store version of Paint.NET](https://www.microsoft.com/store/apps/9NBHCS1LX4R0):
48+
* Put the extracted files in the `<Documents>\paint.net App Files\FileTypes` directory.
49+
* Restart Paint.NET.

SvgFileType.ThirdPartyNotices.txt

Lines changed: 922 additions & 0 deletions
Large diffs are not rendered by default.

SvgFileType/FodyWeavers.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
3-
<ILMerge IncludeAssemblies="Svg|Fizzler" FullImport="true" />
3+
<ILMerge IncludeAssemblies="Svg|Fizzler" NamespacePrefix="SvgFileTypePlugin$" FullImport="true" />
44
</Weavers>

SvgFileType/LayersMode.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
namespace SvgFileTypePlugin
1+
// Copyright 2021 Osman Tunçelli. All rights reserved.
2+
// Use of this source code is governed by a LGPL license that can be
3+
// found in the COPYING file.
4+
5+
namespace SvgFileTypePlugin
26
{
37
internal enum LayersMode
48
{

SvgFileType/MessageBoxEx.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace SvgFileTypePlugin
88
{
99
/// <summary>
1010
/// Parent centered MessageBox dialog in C#
11+
/// https://gist.github.com/otuncelli/bd967d63d0151df14fefb1388e944e4e
1112
/// </summary>
1213
internal static class MessageBoxEx
1314
{

SvgFileType/MyPluginSupportInfo.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2021 Osman Tunçelli. All rights reserved.
2+
// Use of this source code is governed by a LGPL license that can be
3+
// found in the COPYING file.
4+
5+
using PaintDotNet;
6+
using System;
7+
using System.Reflection;
8+
9+
namespace SvgFileTypePlugin
10+
{
11+
public sealed class MyPluginSupportInfo : IPluginSupportInfo, IPluginSupportInfoProvider
12+
{
13+
public const string VersionString = "1.0.4.0";
14+
public const string Url = "https://github.com/otuncelli/Scalable-Vector-Graphics-Plugin-for-Paint.NET";
15+
16+
#region IPluginSupportInfo
17+
public string Author => "Osman Tunçelli";
18+
public string Copyright => ((AssemblyCopyrightAttribute)(typeof(PluginSupportInfo).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)[0])).Copyright;
19+
public string DisplayName => ((AssemblyProductAttribute)GetType().Assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), inherit: false)[0]).Product;
20+
public Version Version => typeof(PluginSupportInfo).Assembly.GetName().Version;
21+
public Uri WebsiteUri => new Uri(Url);
22+
#endregion
23+
24+
#region IPluginSupportInfoProvider
25+
public IPluginSupportInfo GetPluginSupportInfo()
26+
{
27+
return new MyPluginSupportInfo();
28+
}
29+
#endregion
30+
}
31+
}

SvgFileType/PaintGroupBoundaries.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
using Svg;
1+
// Copyright 2021 Osman Tunçelli. All rights reserved.
2+
// Use of this source code is governed by a LGPL license that can be
3+
// found in the COPYING file.
4+
5+
using Svg;
26
using System;
37
using System.Drawing;
48
using System.Drawing.Drawing2D;
59

610
namespace SvgFileTypePlugin
711
{
812
// Used to determine boundaries of a group.
9-
internal class PaintGroupBoundaries : SvgVisualElement
13+
internal sealed class PaintGroupBoundaries : SvgVisualElement
1014
{
11-
public PaintGroupBoundaries(SvgGroup relatedGroup)
15+
public PaintGroupBoundaries(SvgGroup relatedGroup, bool isStart)
1216
{
1317
RelatedGroup = relatedGroup;
18+
IsStart = isStart;
1419
}
1520

1621
public SvgGroup RelatedGroup { get; }
1722

18-
public bool IsStart { get; set; }
23+
public bool IsStart { get; }
1924

2025
public override RectangleF Bounds => throw new NotImplementedException();
2126

SvgFileType/Properties/AssemblyInfo.cs

Lines changed: 0 additions & 40 deletions
This file was deleted.

SvgFileType/SvgDocumentOpener.cs

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,72 @@
1-
using Svg;
1+
// Copyright 2021 Osman Tunçelli. All rights reserved.
2+
// Use of this source code is governed by a LGPL license that can be
3+
// found in the COPYING file.
4+
5+
using Svg;
26
using System;
37
using System.IO;
48
using System.IO.Compression;
59
using System.Linq;
610

711
namespace SvgFileTypePlugin
812
{
9-
/// <summary>
10-
/// Supports opening compressed variant of svg
11-
/// </summary>
12-
internal class SvgDocumentOpener : IDisposable
13+
internal static class SvgDocumentOpener
1314
{
14-
private static readonly byte[] GZipHeaders = {0x1f, 0x8b, 0x8};
15+
public static SvgDocument Open(Stream stream)
16+
{
17+
if (stream == null) throw new ArgumentNullException(nameof(stream), "Input stream can not be null.");
18+
if (!stream.CanRead) throw new IOException("Input stream is not readable.");
1519

16-
private Stream InnerStream { get; }
20+
byte[] first3Bytes = new byte[3];
21+
byte[] gzipHeaderBytes = { 0x1f, 0x8b, 0x8 };
22+
int read = stream.Read(first3Bytes, 0, 3);
23+
if (read < 3) throw new IOException("Input stream does not contain valid svg data.");
1724

18-
private SvgDocumentOpener(Stream input)
19-
{
20-
if (input.Length < 3)
25+
bool svgz = first3Bytes.SequenceEqual(gzipHeaderBytes);
26+
Stream svgStream;
27+
28+
if (stream.CanSeek)
2129
{
22-
throw new InvalidDataException();
30+
stream.Seek(0, SeekOrigin.Begin);
31+
svgStream = svgz ? new GZipStream(stream, CompressionMode.Decompress, true) : stream;
32+
return FromStream(svgStream, svgz);
2333
}
24-
25-
var headerBytes = new byte[3];
26-
input.Read(headerBytes, 0, headerBytes.Length);
27-
input.Position = 0;
28-
29-
// seems like input stream managed by paint.net
30-
// so we leave it open and not dispose it
31-
InnerStream = headerBytes.SequenceEqual(GZipHeaders)
32-
? new GZipStream(input, CompressionMode.Decompress, true)
33-
: input;
34-
}
35-
36-
public static SvgDocument FromStream(Stream stream)
37-
{
38-
using (var wrapper = new SvgDocumentOpener(stream))
34+
else
3935
{
40-
return SvgDocument.Open<SvgDocument>(wrapper.InnerStream);
36+
int length;
37+
try
38+
{
39+
length = (int)stream.Length;
40+
}
41+
catch (NotSupportedException)
42+
{
43+
length = 3;
44+
}
45+
46+
using (var memory = new MemoryStream(length))
47+
{
48+
memory.Write(first3Bytes, 0, 3);
49+
stream.CopyTo(memory);
50+
memory.Seek(0, SeekOrigin.Begin);
51+
svgStream = svgz ? (Stream)new GZipStream(memory, CompressionMode.Decompress, false) : memory;
52+
return FromStream(svgStream, svgz);
53+
}
4154
}
4255
}
4356

44-
#region IDisposable
45-
46-
private bool disposed;
47-
48-
public void Dispose()
57+
private static SvgDocument FromStream(Stream stream, bool svgz)
4958
{
50-
if (disposed)
59+
try
5160
{
52-
return;
61+
return SvgDocument.Open<SvgDocument>(stream);
5362
}
54-
55-
// seems like input stream managed by paint.net
56-
// so we leave it open and not dispose it.
57-
// we only dispose the GZipStream created by
58-
// this object.
59-
if (InnerStream is GZipStream)
63+
finally
6064
{
61-
InnerStream.Dispose();
65+
if (svgz)
66+
{
67+
stream.Dispose();
68+
}
6269
}
63-
64-
disposed = true;
6570
}
66-
67-
#endregion
6871
}
6972
}

SvgFileType/SvgElementExtensions.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1-
using Svg;
1+
// Copyright 2021 Osman Tunçelli. All rights reserved.
2+
// Use of this source code is governed by a LGPL license that can be
3+
// found in the COPYING file.
4+
5+
using Svg;
26
using System.Reflection;
37

48
namespace SvgFileTypePlugin
59
{
610
internal static class SvgElementExtensions
711
{
8-
private static readonly MethodInfo ElementNameGetter =
9-
typeof(SvgElement).GetProperty("ElementName",
10-
BindingFlags.NonPublic | BindingFlags.Instance)?.GetGetMethod(true);
12+
private static readonly MethodInfo ElementNameGetter = typeof(SvgElement).GetProperty("ElementName", BindingFlags.NonPublic | BindingFlags.Instance)?.GetGetMethod(true);
13+
private static readonly MethodInfo AttributesGetter = typeof(SvgElement).GetProperty("Attributes", BindingFlags.NonPublic | BindingFlags.Instance)?.GetGetMethod(true);
1114

1215
public static string GetName(this SvgElement element)
1316
{
1417
return element.GetType().GetCustomAttribute<SvgElementAttribute>()?.ElementName ??
15-
ElementNameGetter?.Invoke(element, null) as string ??
18+
ElementNameGetter.Invoke(element, null) as string ??
1619
element.GetType().Name;
1720
}
21+
22+
public static SvgAttributeCollection GetAttributes(this SvgElement element)
23+
{
24+
return (SvgAttributeCollection)AttributesGetter.Invoke(element, null);
25+
}
1826
}
1927
}

0 commit comments

Comments
 (0)