diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs index 457bc09..1e32edb 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs @@ -15,15 +15,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using QuickLook.Common.Helpers; +using QuickLook.Common.Plugin; +using QuickLook.Plugin.ImageViewer.AnimatedImage.Providers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows; using System.Windows.Input; -using QuickLook.Common.Helpers; -using QuickLook.Common.Plugin; -using QuickLook.Plugin.ImageViewer.AnimatedImage.Providers; namespace QuickLook.Plugin.ImageViewer; @@ -57,6 +57,9 @@ public class Plugin : IViewer private ImagePanel _ip; private MetaProvider _meta; + private SvgImagePanel _ipSvg; + private SvgMetaProvider _metaSvg; + public int Priority => 0; public void Init() @@ -109,6 +112,23 @@ public class Plugin : IViewer public void Prepare(string path, ContextObject context) { + if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)) + { + if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer")) + { + _metaSvg = new SvgMetaProvider(path); + var sizeSvg = _metaSvg.GetSize(); + + if (!sizeSvg.IsEmpty) + context.SetPreferredSizeFit(sizeSvg, 0.8d); + else + context.PreferredSize = new Size(800, 600); + + context.Theme = (Themes)SettingHelper.Get("LastTheme", 1, "QuickLook.Plugin.ImageViewer"); + return; + } + } + _meta = new MetaProvider(path); var size = _meta.GetSize(); @@ -123,6 +143,26 @@ public class Plugin : IViewer public void View(string path, ContextObject context) { + if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)) + { + if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer")) + { + _ipSvg = new SvgImagePanel(); + _ipSvg.PreviewSvg(path); + + var sizeSvg = _metaSvg.GetSize(); + + context.ViewerContent = _ip; + context.Title = sizeSvg.IsEmpty + ? $"{Path.GetFileName(path)}" + : $"{sizeSvg.Width}×{sizeSvg.Height}: {Path.GetFileName(path)}"; + + context.ViewerContent = _ipSvg; + context.IsBusy = false; + return; + } + } + _ip = new ImagePanel(context, _meta); var size = _meta.GetSize(); @@ -142,7 +182,12 @@ public class Plugin : IViewer public void Cleanup() { + GC.SuppressFinalize(this); + _ip?.Dispose(); _ip = null; + + _ipSvg?.Dispose(); + _ipSvg = null; } } diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html index 9c277e1..8e53194 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html +++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html @@ -21,7 +21,7 @@ #svgWrapper { transform-origin: center center; - transition: transform 0.05s ease-out; + transition: transform 0.1s ease-out; } diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js index b87bc45..2a53c59 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js +++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js @@ -14,7 +14,7 @@ document.addEventListener("wheel", (e) => { e.preventDefault(); - const scaleFactor = 1.1; + const scaleFactor = 1.2; if (e.deltaY < 0) { scale *= scaleFactor; diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs new file mode 100644 index 0000000..8e11179 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs @@ -0,0 +1,75 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using System.Windows; +using System.Xml.Linq; + +namespace QuickLook.Plugin.ImageViewer; + +public class SvgMetaProvider(string path) +{ + private readonly string _path = path; + private Size _size = Size.Empty; + + public Size GetSize() + { + if (_size != Size.Empty) + { + return _size; + } + + if (!File.Exists(_path)) + { + return _size; + } + try + { + var svgContent = File.ReadAllText(_path); + var svg = XElement.Parse(svgContent); + XNamespace ns = svg.Name.Namespace; + + string widthAttr = svg.Attribute("width")?.Value; + string heightAttr = svg.Attribute("height")?.Value; + + float? width = TryParseSvgLength(widthAttr); + float? height = TryParseSvgLength(heightAttr); + + if (width.HasValue && height.HasValue) + { + _size = new Size { Width = width.Value, Height = height.Value }; + } + + string viewBoxAttr = svg.Attribute("viewBox")?.Value; + if (!string.IsNullOrEmpty(viewBoxAttr)) + { + var parts = viewBoxAttr.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries); + if (parts.Length == 4 && + float.TryParse(parts[2], out float vbWidth) && + float.TryParse(parts[3], out float vbHeight)) + { + _size = new Size { Width = vbWidth, Height = vbHeight }; + } + } + } + catch (Exception e) + { + Debug.WriteLine(e); + } + + return _size; + } + + private static float? TryParseSvgLength(string input) + { + if (string.IsNullOrEmpty(input)) + return null; + + var match = Regex.Match(input.Trim(), @"^([\d.]+)(px|pt|mm|cm|in|em|ex|%)?$", RegexOptions.IgnoreCase); + if (match.Success && float.TryParse(match.Groups[1].Value, out float value)) + { + return value; + } + return null; + } +}