From 2b0e32916d976c92ba1fca06a2ffc8f2c3108a0b Mon Sep 17 00:00:00 2001 From: Drakula44 <35308381+Drakula44@users.noreply.github.com> Date: Mon, 22 Feb 2021 18:35:41 +0100 Subject: [PATCH] Svg image preview is displayed unscaled and uncentered (#8996) * Fixed screen centering and scaling problem with SVG files * Little shorter code. * Improved exception caching * typo * fixed upscaling problem * add CSS that IE6 can support it * typo * adding in spelling Co-authored-by: Clint Rutkas --- .github/actions/spell-check/expect.txt | 4 + .../SvgPreviewHandler/SvgPreviewControl.cs | 14 ++- .../Utilities/SvgPreviewHandlerHelper.cs | 95 +++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 7cec956dac..a21a031b39 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -2335,6 +2335,8 @@ vk VKey VKTAB vm +vmax +vmin Voicemail VOS VREDRAW @@ -2348,6 +2350,7 @@ VSTS VSTT VTABLE Vtbl +vw Vx watsonportal wav @@ -2480,6 +2483,7 @@ xa xamarin xaml XAngle +XAttribute xbf XBind XBUTTON diff --git a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs index 779921d925..826d85c425 100644 --- a/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs +++ b/src/modules/previewpane/SvgPreviewHandler/SvgPreviewControl.cs @@ -65,6 +65,18 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg return; } + try + { + svgData = SvgPreviewHandlerHelper.AddStyleSVG(svgData); + } +#pragma warning disable CA1031 // Do not catch general exception types + catch (Exception ex) +#pragma warning restore CA1031 // Do not catch general exception types + { + _browser.ScrollBarsEnabled = true; + PowerToysTelemetry.Log.WriteEvent(new SvgFilePreviewError { Message = ex.Message }); + } + InvokeOnControlThread(() => { try @@ -127,7 +139,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg _browser.Dock = DockStyle.Fill; _browser.IsWebBrowserContextMenuEnabled = false; _browser.ScriptErrorsSuppressed = true; - _browser.ScrollBarsEnabled = true; + _browser.ScrollBarsEnabled = false; _browser.AllowNavigation = false; Controls.Add(_browser); } diff --git a/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs index c5af5df681..4fab187322 100644 --- a/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs +++ b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs @@ -68,5 +68,100 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg.Utilities return foundBlockedElement; } + + /// + /// Add proper + /// + /// Input Svg + /// Returns modified svgData with added style + public static string AddStyleSVG(string stringSvgData) + { + XElement svgData = XElement.Parse(stringSvgData); + + var attributes = svgData.Attributes(); + string width = string.Empty; + string height = string.Empty; + string widthR = string.Empty; + string heightR = string.Empty; + string oldStyle = string.Empty; + + // Get width and height of element and remove it afterwards because it will be added inside style attribute + for (int i = 0; i < attributes.Count(); i++) + { + if (attributes.ElementAt(i).Name == "height") + { + height = attributes.ElementAt(i).Value; + attributes.ElementAt(i).Remove(); + i--; + } + else if (attributes.ElementAt(i).Name == "width") + { + width = attributes.ElementAt(i).Value; + attributes.ElementAt(i).Remove(); + i--; + } + else if (attributes.ElementAt(i).Name == "style") + { + oldStyle = attributes.ElementAt(i).Value; + attributes.ElementAt(i).Remove(); + i--; + } + } + + svgData.ReplaceAttributes(attributes); + + height = CheckUnit(height); + width = CheckUnit(width); + heightR = RemoveUnit(height); + widthR = RemoveUnit(width); + + string centering = "position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"; + + // Because WebBrowser class is based on IE version that do not support max-width and max-height extra CSS is needed for it to work. + string scaling = $"max-width: {width} ; max-height: {height} ;"; + scaling += $" _height:expression(this.scrollHeight > {heightR} ? \" {height}\" : \"auto\"); _width:expression(this.scrollWidth > {widthR} ? \"{width}\" : \"auto\");"; + + svgData.Add(new XAttribute("style", scaling + centering + oldStyle)); + return svgData.ToString(); + } + + /// + /// If there is a CSS unit at the end return the same string, else return the string with a px unit at the end + /// + /// CSS length + /// Returns modified length + private static string CheckUnit(string length) + { + string[] cssUnits = { "cm", "mm", "in", "px", "pt", "pc", "em", "ex", "ch", "rem", "vw", "vh", "vmin", "vmax", "%" }; + foreach (var unit in cssUnits) + { + if (length.EndsWith(unit, System.StringComparison.CurrentCultureIgnoreCase)) + { + return length; + } + } + + return length + "px"; + } + + /// + /// Remove a CSS unit from the end of the string + /// + /// CSS length + /// Returns modified length + private static string RemoveUnit(string length) + { + string[] cssUnits = { "cm", "mm", "in", "px", "pt", "pc", "em", "ex", "ch", "rem", "vw", "vh", "vmin", "vmax", "%" }; + foreach (var unit in cssUnits) + { + if (length.EndsWith(unit, System.StringComparison.CurrentCultureIgnoreCase)) + { + length = length.Remove(length.Length - unit.Length); + return length; + } + } + + return length; + } } }