From 4fd25f4eb43367b87d854fb176c5880ecde8b401 Mon Sep 17 00:00:00 2001 From: James South Date: Mon, 6 Apr 2015 00:11:34 +0100 Subject: [PATCH] Transferring more processors. Former-commit-id: 249d2715f40b60384076d3710d91070ed5342db6 Former-commit-id: f339fc46f58eca21106100cf918416a703e7ff7b Former-commit-id: d3d169819d61c264bd9564263b87c88772b5fda6 --- .../ExtendedColorTypeConverter.cs | 42 ++- .../QuerystringParser/FontFamilyConverter.cs | 141 +++++++++ .../QuerystringParser/QueryParamParser.cs | 9 + .../HttpModules/ImageProcessingModule.cs | 45 ++- .../ImageProcessor.Web.csproj | 1 + src/ImageProcessor.Web/Processors/Alpha.cs | 1 - .../Processors/Brightness.cs | 4 +- src/ImageProcessor.Web/Processors/Contrast.cs | 4 +- .../Processors/DetectEdges.cs | 2 +- .../Processors/EntropyCrop.cs | 1 - src/ImageProcessor.Web/Processors/Resize.cs | 239 +++------------ src/ImageProcessor.Web/Processors/Rotate.cs | 27 +- .../Processors/RotateBounded.cs | 30 +- .../Processors/RoundedCorners.cs | 112 ++----- .../Processors/Saturation.cs | 32 +- src/ImageProcessor.Web/Processors/Tint.cs | 26 +- src/ImageProcessor.Web/Processors/Vignette.cs | 34 +-- .../Processors/Watermark.cs | 283 +++++------------- .../MVC/Views/Home/External.cshtml | 9 + src/TestWebsites/MVC/Web.config | 9 + 20 files changed, 452 insertions(+), 599 deletions(-) create mode 100644 src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs diff --git a/src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs b/src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs index eec3d145c..612c93d37 100644 --- a/src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs +++ b/src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs @@ -26,7 +26,12 @@ namespace ImageProcessor.Web.Helpers /// /// The web color regex. /// - private static readonly Regex WebColorRegex = new Regex("([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); + private static readonly Regex HexColorRegex = new Regex("([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); + + /// + /// The number color regex. + /// + private static readonly Regex NumberRegex = new Regex(@"\d+", RegexOptions.Compiled); /// /// The html system color table map. @@ -68,9 +73,42 @@ namespace ImageProcessor.Web.Helpers return Color.LightGray; } + // Handle a,r,g,b + char separator = culture.TextInfo.ListSeparator[0]; + if (colorText.Contains(separator.ToString())) + { + string[] components = colorText.Split(separator); + + bool convert = true; + foreach (string component in components) + { + if (!NumberRegex.IsMatch(component)) + { + convert = false; + } + } + + if (convert) + { + if (components.Length == 4) + { + return Color.FromArgb( + Convert.ToInt32(components[0]), + Convert.ToInt32(components[1]), + Convert.ToInt32(components[2]), + Convert.ToInt32(components[3])); + } + + return Color.FromArgb( + Convert.ToInt32(components[0]), + Convert.ToInt32(components[1]), + Convert.ToInt32(components[2])); + } + } + // Hex based color values. char hash = colorText[0]; - if (hash == '#' || WebColorRegex.IsMatch(colorText)) + if (hash == '#' || HexColorRegex.IsMatch(colorText)) { if (hash != '#') { diff --git a/src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs b/src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs new file mode 100644 index 000000000..e3705cdcc --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs @@ -0,0 +1,141 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// FontFamilyConverter - converter class for converting between the +// and types. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + using System.ComponentModel; + using System.Drawing; + using System.Globalization; + + /// + /// FontFamilyConverter - converter class for converting between the + /// and types. + /// + public class FontFamilyConverter : TypeConverter + { + /// + /// Returns whether this converter can convert an object of the given type to the type of + /// this converter, using the specified context. + /// + /// + /// true if this converter can perform the conversion; otherwise, false. + /// + /// + /// An that provides a format context. + /// + /// + /// A that represents the type you want to convert from. + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + + return base.CanConvertFrom(context, sourceType); + } + + /// + /// Returns whether this converter can convert the object to the specified type, using + /// the specified context. + /// + /// + /// true if this converter can perform the conversion; otherwise, false. + /// + /// + /// An that provides a format context. + /// + /// + /// A that represents the type you want to convert to. + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string) || destinationType == typeof(FontFamily)) + { + return true; + } + + return base.CanConvertTo(context, destinationType); + } + + /// + /// Converts the given object to the type of this converter, using the specified context and + /// culture information. + /// + /// + /// An that represents the converted value. + /// + /// + /// An that provides a format context. + /// + /// + /// The to use as the current culture. + /// + /// The to convert. + /// The conversion cannot be performed. + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + string s = value as string; + if (!string.IsNullOrWhiteSpace(s)) + { + return new FontFamily(s); + } + + return base.ConvertFrom(context, culture, value); + } + + /// + /// Converts the given value object to the specified type, using the specified context and culture + /// information. + /// + /// + /// An that represents the converted value. + /// + /// + /// An that provides a format context. + /// + /// + /// A . If null is passed, the current culture is assumed. + /// The to convert. + /// + /// The to convert the parameter to. + /// + /// The parameter is null. + /// The conversion cannot be performed. + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (null == value) + { + throw new ArgumentNullException("value"); + } + + FontFamily fontFamily = value as FontFamily; + if (fontFamily == null) + { + throw new ArgumentException("value"); + } + + if (null == destinationType) + { + throw new ArgumentNullException("destinationType"); + } + + if (destinationType == typeof(string)) + { + return fontFamily.Name; + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} diff --git a/src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs b/src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs index 24a3e252f..b6758f633 100644 --- a/src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs +++ b/src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs @@ -41,6 +41,7 @@ namespace ImageProcessor.Web.Helpers private QueryParamParser() { this.AddColorConverters(); + this.AddFontFamilyConverters(); this.AddListConverters(); this.AddArrayConverters(); } @@ -138,6 +139,14 @@ namespace ImageProcessor.Web.Helpers this.AddTypeConverter(typeof(Color), typeof(ExtendedColorTypeConverter)); } + /// + /// Adds font family converters. + /// + private void AddFontFamilyConverters() + { + this.AddTypeConverter(typeof(FontFamily), typeof(FontFamilyConverter)); + } + /// /// Adds a selection of default list type converters. /// diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index 4b482b16e..04f808b0b 100644 --- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -3,7 +3,11 @@ // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // +// +// Processes any image requests within the web application. +// // -------------------------------------------------------------------------------------------------------------------- + namespace ImageProcessor.Web.HttpModules { using System; @@ -45,10 +49,15 @@ namespace ImageProcessor.Web.HttpModules private const string CachedResponseFileDependency = "CACHED_IMAGE_DEPENDENCY_054F217C-11CF-49FF-8D2F-698E8E6EB58F"; /// - /// The regular expression to search strings for. + /// The regular expression to search strings for presets with. /// private static readonly Regex PresetRegex = new Regex(@"preset=[^&]+", RegexOptions.Compiled); + /// + /// The regular expression to search strings for protocols with. + /// + private static readonly Regex ProtocolRegex = new Regex("http(s)?://", RegexOptions.Compiled); + /// /// The assembly version. /// @@ -295,26 +304,28 @@ namespace ImageProcessor.Web.HttpModules if (currentService != null) { bool isFileLocal = currentService.IsFileLocalService; - bool hasMultiParams = request.Url.ToString().Count(f => f == '?') > 1; + string url = request.Url.ToString(); + bool isLegacy = ProtocolRegex.Matches(url).Count > 1; + bool hasMultiParams = url.Count(f => f == '?') > 1; string requestPath = string.Empty; string queryString = string.Empty; string urlParameters = string.Empty; // Legacy support. I'd like to remove this asap. - if (hasMultiParams) + if (isLegacy && hasMultiParams) { // We need to split the querystring to get the actual values we want. - string urlDecode = HttpUtility.UrlDecode(request.QueryString.ToString()); + string multiQuery = request.QueryString.ToString(); - if (!string.IsNullOrWhiteSpace(urlDecode)) + if (!string.IsNullOrWhiteSpace(multiQuery)) { // UrlDecode seems to mess up in some circumstance. - if (urlDecode.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) + if (multiQuery.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) { - urlDecode = urlDecode.Replace(":/", "://"); + multiQuery = multiQuery.Replace(":/", "://"); } - string[] paths = urlDecode.Split('?'); + string[] paths = multiQuery.Split('?'); requestPath = paths[0]; @@ -335,7 +346,7 @@ namespace ImageProcessor.Web.HttpModules if (string.IsNullOrWhiteSpace(currentService.Prefix)) { requestPath = HostingEnvironment.MapPath(request.Path); - queryString = HttpUtility.UrlDecode(request.QueryString.ToString()); + queryString = request.QueryString.ToString(); } else { @@ -344,8 +355,20 @@ namespace ImageProcessor.Web.HttpModules ? currentService.Settings["Protocol"] + "://" : string.Empty; - requestPath = protocol + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/'); - queryString = HttpUtility.UrlDecode(request.QueryString.ToString()); + // Handle requests that require parameters. + if (hasMultiParams) + { + string[] paths = url.Split('?'); + requestPath = protocol + + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/') + + "?" + paths[1]; + queryString = paths[2]; + } + else + { + requestPath = protocol + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/'); + queryString = request.QueryString.ToString(); + } } } diff --git a/src/ImageProcessor.Web/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj index 6e11da1ee..c57b38b05 100644 --- a/src/ImageProcessor.Web/ImageProcessor.Web.csproj +++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj @@ -53,6 +53,7 @@ + diff --git a/src/ImageProcessor.Web/Processors/Alpha.cs b/src/ImageProcessor.Web/Processors/Alpha.cs index 5be42894b..24f1e037e 100644 --- a/src/ImageProcessor.Web/Processors/Alpha.cs +++ b/src/ImageProcessor.Web/Processors/Alpha.cs @@ -10,7 +10,6 @@ namespace ImageProcessor.Web.Processors { - using System; using System.Collections.Specialized; using System.Text.RegularExpressions; using System.Web; diff --git a/src/ImageProcessor.Web/Processors/Brightness.cs b/src/ImageProcessor.Web/Processors/Brightness.cs index 0415d7de3..b1ff158c4 100644 --- a/src/ImageProcessor.Web/Processors/Brightness.cs +++ b/src/ImageProcessor.Web/Processors/Brightness.cs @@ -26,7 +26,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"brightness=\d+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"brightness=(-)?\d+", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -74,7 +74,7 @@ namespace ImageProcessor.Web.Processors this.SortOrder = match.Index; NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); int percentage = QueryParamParser.Instance.ParseValue(queryCollection["brightness"]); - percentage = ImageMaths.Clamp(percentage, 0, 100); + percentage = ImageMaths.Clamp(percentage, -100, 100); this.Processor.DynamicParameter = percentage; } diff --git a/src/ImageProcessor.Web/Processors/Contrast.cs b/src/ImageProcessor.Web/Processors/Contrast.cs index da1e79021..ee25c48ba 100644 --- a/src/ImageProcessor.Web/Processors/Contrast.cs +++ b/src/ImageProcessor.Web/Processors/Contrast.cs @@ -26,7 +26,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"contrast=\d+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"contrast=(-)?\d+", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -74,7 +74,7 @@ namespace ImageProcessor.Web.Processors this.SortOrder = match.Index; NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); int percentage = QueryParamParser.Instance.ParseValue(queryCollection["contrast"]); - percentage = ImageMaths.Clamp(percentage, 0, 100); + percentage = ImageMaths.Clamp(percentage, -100, 100); this.Processor.DynamicParameter = percentage; } diff --git a/src/ImageProcessor.Web/Processors/DetectEdges.cs b/src/ImageProcessor.Web/Processors/DetectEdges.cs index 5dd2312e7..986a7d253 100644 --- a/src/ImageProcessor.Web/Processors/DetectEdges.cs +++ b/src/ImageProcessor.Web/Processors/DetectEdges.cs @@ -90,7 +90,7 @@ namespace ImageProcessor.Web.Processors { this.SortOrder = match.Index; NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); - IEdgeFilter filter = (IEdgeFilter)detectors[queryCollection["detectedges"]]; + IEdgeFilter filter = (IEdgeFilter)detectors[QueryParamParser.Instance.ParseValue(queryCollection["detectedges"])]; bool greyscale = QueryParamParser.Instance.ParseValue(queryCollection["greyscale"]); this.Processor.DynamicParameter = new Tuple(filter, greyscale); } diff --git a/src/ImageProcessor.Web/Processors/EntropyCrop.cs b/src/ImageProcessor.Web/Processors/EntropyCrop.cs index 1db05e71c..41c5f177d 100644 --- a/src/ImageProcessor.Web/Processors/EntropyCrop.cs +++ b/src/ImageProcessor.Web/Processors/EntropyCrop.cs @@ -14,7 +14,6 @@ namespace ImageProcessor.Web.Processors using System.Text.RegularExpressions; using System.Web; - using ImageProcessor.Common.Extensions; using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; diff --git a/src/ImageProcessor.Web/Processors/Resize.cs b/src/ImageProcessor.Web/Processors/Resize.cs index e8dc9bda7..5e9b228b8 100644 --- a/src/ImageProcessor.Web/Processors/Resize.cs +++ b/src/ImageProcessor.Web/Processors/Resize.cs @@ -12,14 +12,15 @@ namespace ImageProcessor.Web.Processors { using System; using System.Collections.Generic; + using System.Collections.Specialized; using System.Drawing; using System.Linq; - using System.Text; using System.Text.RegularExpressions; + using System.Web; using ImageProcessor.Imaging; using ImageProcessor.Processors; - using ImageProcessor.Web.Extensions; + using ImageProcessor.Web.Helpers; /// /// Resizes an image to the given dimensions. @@ -29,37 +30,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"(width|height)=|(width|height)ratio=|mode=(carve|percent)?|anchor=|center=|upscale=", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the size attribute. - /// - private static readonly Regex SizeRegex = new Regex(@"(width|height)=\d+(.\d+)?", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the ratio attribute. - /// - private static readonly Regex RatioRegex = new Regex(@"(width|height)ratio=\d+(.\d+)?", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the mode attribute. - /// - private static readonly Regex ModeRegex = new Regex(@"mode=(pad|stretch|crop|max)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the anchor attribute. - /// - private static readonly Regex AnchorRegex = new Regex(@"anchor=(top|bottom|left|right|center)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the center attribute. - /// - private static readonly Regex CenterRegex = new Regex(@"center=\d+(.\d+)?[,-]\d+(.\d+)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the upscale attribute. - /// - private static readonly Regex UpscaleRegex = new Regex(@"upscale=false", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"(width|height)=((.)?\d+|\d+(.\d+)?)+", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -93,54 +64,33 @@ namespace ImageProcessor.Web.Processors /// /// The position in the original string where the first character of the captured substring was found. /// - /// The query string to search. + /// + /// The query string to search. + /// /// /// The zero-based starting position in the original string where the captured substring was found. /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - // First merge the matches so we can parse . - StringBuilder stringBuilder = new StringBuilder(); - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - // We don't want any resize carve or percentile crops requests to interfere. - // TODO: This is hacky and awful and should go. - if (match.Value.ToUpperInvariant().Contains("CARVE") || match.Value.ToUpperInvariant().Contains("PERCENT")) - { - continue; - } - - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - stringBuilder.Append(queryString); - } - - index += 1; - } - } - - if (this.SortOrder < int.MaxValue) + if (match.Success) { - // Match syntax - string toParse = stringBuilder.ToString(); + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + Size size = this.ParseSize(queryCollection); + ResizeMode mode = QueryParamParser.Instance.ParseValue(queryCollection["mode"]); + AnchorPosition position = QueryParamParser.Instance.ParseValue(queryCollection["anchor"]); + bool upscale = queryCollection["upscale"] == null || QueryParamParser.Instance.ParseValue(queryCollection["upscale"]); + float[] center = QueryParamParser.Instance.ParseValue(queryCollection["center"]); - Size size = this.ParseSize(toParse); ResizeLayer resizeLayer = new ResizeLayer(size) { - ResizeMode = this.ParseMode(toParse), - AnchorPosition = this.ParsePosition(toParse), - Upscale = !UpscaleRegex.IsMatch(toParse), - CenterCoordinates = this.ParseCoordinates(toParse), + ResizeMode = mode, + AnchorPosition = position, + Upscale = upscale, + CenterCoordinates = center }; this.Processor.DynamicParameter = resizeLayer; @@ -151,168 +101,65 @@ namespace ImageProcessor.Web.Processors ((ImageProcessor.Processors.Resize)this.Processor).RestrictedSizes = this.ParseRestrictions( restrictions); } - + return this.SortOrder; } /// - /// Returns the correct for the given string. + /// Returns the correct for the given query collection. /// - /// - /// The input string containing the value to parse. + /// + /// The containing the query parameters to parse. /// /// /// The . /// - private Size ParseSize(string input) + private Size ParseSize(NameValueCollection queryCollection) { - const string Width = "width="; - const string Height = "height="; - const string WidthRatio = "widthratio="; - const string HeightRatio = "heightratio="; + string width = queryCollection["width"]; + string height = queryCollection["height"]; + string widthRatio = queryCollection["widthratio"]; + string heightRatio = queryCollection["heightratio"]; Size size = new Size(); - // First merge the matches so we can parse . - StringBuilder stringBuilder = new StringBuilder(); - foreach (Match match in SizeRegex.Matches(input)) - { - stringBuilder.Append(match.Value); - } - // First cater for single dimensions. - string value = stringBuilder.ToString(); - - if (input.Contains(Width) && !input.Contains(Height)) + if (width != null && height == null) { - size = new Size(Convert.ToInt32(value.ToPositiveFloatArray()[0]), 0); + size = new Size(QueryParamParser.Instance.ParseValue(width), 0); } - if (input.Contains(Height) && !input.Contains(Width)) + if (width == null && height != null) { - size = new Size(0, Convert.ToInt32(value.ToPositiveFloatArray()[0])); + size = new Size(0, QueryParamParser.Instance.ParseValue(height)); } - // Both dimensions supplied. - if (input.Contains(Height) && input.Contains(Width)) + // Both supplied + if (width != null && height != null) { - float[] dimensions = value.ToPositiveFloatArray(); - - // Check the order in which they have been supplied. - size = input.IndexOf(Width, StringComparison.Ordinal) < input.IndexOf(Height, StringComparison.Ordinal) - ? new Size(Convert.ToInt32(dimensions[0]), Convert.ToInt32(dimensions[1])) - : new Size(Convert.ToInt32(dimensions[1]), Convert.ToInt32(dimensions[0])); + size = new Size( + QueryParamParser.Instance.ParseValue(width), + QueryParamParser.Instance.ParseValue(height)); } // Calculate any ratio driven sizes. if (size.Width == 0 || size.Height == 0) { - stringBuilder.Clear(); - foreach (Match match in RatioRegex.Matches(input)) - { - stringBuilder.Append(match.Value); - } - - value = stringBuilder.ToString(); - // Replace 0 width - if (size.Width == 0 && size.Height > 0 && input.Contains(WidthRatio) && !input.Contains(HeightRatio)) + if (size.Width == 0 && size.Height > 0 && widthRatio != null && heightRatio == null) { - size.Width = Convert.ToInt32(value.ToPositiveFloatArray()[0] * size.Height); + size.Width = Convert.ToInt32(QueryParamParser.Instance.ParseValue(widthRatio) * size.Height); } // Replace 0 height - if (size.Height == 0 && size.Width > 0 && input.Contains(HeightRatio) && !input.Contains(WidthRatio)) + if (size.Width > 0 && size.Height == 0 && widthRatio == null && heightRatio != null) { - size.Height = Convert.ToInt32(value.ToPositiveFloatArray()[0] * size.Width); + size.Height = Convert.ToInt32(QueryParamParser.Instance.ParseValue(heightRatio) * size.Width); } } return size; } - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private ResizeMode ParseMode(string input) - { - foreach (Match match in ModeRegex.Matches(input)) - { - // Split on = - string mode = match.Value.Split('=')[1]; - - switch (mode) - { - case "stretch": - return ResizeMode.Stretch; - case "crop": - return ResizeMode.Crop; - case "max": - return ResizeMode.Max; - default: - return ResizeMode.Pad; - } - } - - return ResizeMode.Pad; - } - - /// - /// Returns the correct for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct . - /// - private AnchorPosition ParsePosition(string input) - { - foreach (Match match in AnchorRegex.Matches(input)) - { - // Split on = - string anchor = match.Value.Split('=')[1]; - - switch (anchor) - { - case "top": - return AnchorPosition.Top; - case "bottom": - return AnchorPosition.Bottom; - case "left": - return AnchorPosition.Left; - case "right": - return AnchorPosition.Right; - default: - return AnchorPosition.Center; - } - } - - return AnchorPosition.Center; - } - - /// - /// Parses the coordinates. - /// - /// The input. - /// The array containing the coordinates - private float[] ParseCoordinates(string input) - { - float[] floats = { }; - - foreach (Match match in CenterRegex.Matches(input)) - { - floats = match.Value.ToPositiveFloatArray(); - } - - return floats; - } - /// /// Returns a of sizes to restrict resizing to. /// @@ -328,7 +175,7 @@ namespace ImageProcessor.Web.Processors if (!string.IsNullOrWhiteSpace(input)) { - sizes.AddRange(input.Split(',').Select(this.ParseSize)); + sizes.AddRange(input.Split(',').Select(q => this.ParseSize(HttpUtility.ParseQueryString(q)))); } return sizes; diff --git a/src/ImageProcessor.Web/Processors/Rotate.cs b/src/ImageProcessor.Web/Processors/Rotate.cs index fd2deb42b..2ff29b867 100644 --- a/src/ImageProcessor.Web/Processors/Rotate.cs +++ b/src/ImageProcessor.Web/Processors/Rotate.cs @@ -10,7 +10,10 @@ namespace ImageProcessor.Web.Processors { + using System.Collections.Specialized; using System.Text.RegularExpressions; + using System.Web; + using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; @@ -22,7 +25,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"(^(rotate|angle)|[^.](&,)?rotate|angle)(=|-)[^&|,]+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"rotate=[^&]", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -32,7 +35,6 @@ namespace ImageProcessor.Web.Processors this.Processor = new ImageProcessor.Processors.Rotate(); } - #region IGraphicsProcessor Members /// /// Gets the regular expression to search strings for. /// @@ -69,28 +71,17 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - this.Processor.DynamicParameter = CommonParameterParserUtility.ParseAngle(match.Value); - } - - index += 1; - } + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + this.Processor.DynamicParameter = QueryParamParser.Instance.ParseValue(queryCollection["rotate"]); } return this.SortOrder; } - #endregion } } diff --git a/src/ImageProcessor.Web/Processors/RotateBounded.cs b/src/ImageProcessor.Web/Processors/RotateBounded.cs index eeffec527..aa847a7a5 100644 --- a/src/ImageProcessor.Web/Processors/RotateBounded.cs +++ b/src/ImageProcessor.Web/Processors/RotateBounded.cs @@ -11,7 +11,10 @@ namespace ImageProcessor.Web.Processors { using System; + using System.Collections.Specialized; using System.Text.RegularExpressions; + using System.Web; + using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; @@ -23,7 +26,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"rotatebounded=[^&]+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"rotatebounded=[^&]", RegexOptions.Compiled); /// /// The regular expression to search for. @@ -75,28 +78,17 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - float angle = CommonParameterParserUtility.ParseAngle(match.Value); - bool keepSize = BoundRegex.Match(queryString).Success; - Tuple rotateParams = new Tuple(angle, keepSize); - - this.Processor.DynamicParameter = rotateParams; - } + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + float angle = QueryParamParser.Instance.ParseValue(queryCollection["rotatebounded"]); + bool keepSize = BoundRegex.Match(queryString).Success; - index += 1; - } + this.Processor.DynamicParameter = new Tuple(angle, keepSize); } return this.SortOrder; diff --git a/src/ImageProcessor.Web/Processors/RoundedCorners.cs b/src/ImageProcessor.Web/Processors/RoundedCorners.cs index 001130c14..1ba8cdff9 100644 --- a/src/ImageProcessor.Web/Processors/RoundedCorners.cs +++ b/src/ImageProcessor.Web/Processors/RoundedCorners.cs @@ -10,10 +10,13 @@ namespace ImageProcessor.Web.Processors { - using System.Globalization; + using System.Collections.Specialized; using System.Text.RegularExpressions; + using System.Web; + using ImageProcessor.Imaging; using ImageProcessor.Processors; + using ImageProcessor.Web.Helpers; /// /// Encapsulates methods to add rounded corners to an image. @@ -23,32 +26,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"roundedcorners=[^&]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the angle attribute. - /// - private static readonly Regex RadiusRegex = new Regex(@"(roundedcorners|radius)(=|-)(\d+)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the top left attribute. - /// - private static readonly Regex TopLeftRegex = new Regex(@"tl(=|-)(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the top right attribute. - /// - private static readonly Regex TopRightRegex = new Regex(@"tr(=|-)(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the bottom left attribute. - /// - private static readonly Regex BottomLeftRegex = new Regex(@"bl(=|-)(true|false)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the bottom right attribute. - /// - private static readonly Regex BottomRightRegex = new Regex(@"br(=|-)(true|false)", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"roundedcorners=\d+", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -88,86 +66,42 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer( - this.ParseRadius(queryString), - this.ParseCorner(TopLeftRegex, queryString), - this.ParseCorner(TopRightRegex, queryString), - this.ParseCorner(BottomLeftRegex, queryString), - this.ParseCorner(BottomRightRegex, queryString)); + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); - this.Processor.DynamicParameter = roundedCornerLayer; - } + RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer( + QueryParamParser.Instance.ParseValue(queryCollection["roundedcorners"]), + this.ParseCorner(queryCollection, "tl"), + this.ParseCorner(queryCollection, "tr"), + this.ParseCorner(queryCollection, "bl"), + this.ParseCorner(queryCollection, "br")); - index += 1; - } + this.Processor.DynamicParameter = roundedCornerLayer; } return this.SortOrder; } - #region Private Methods - /// - /// Returns the correct containing the radius for the given string. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The correct containing the radius for the given string. - /// - private int ParseRadius(string input) - { - foreach (Match match in RadiusRegex.Matches(input)) - { - // Split on radius- - int radius; - int.TryParse(match.Value.Split(new[] { '=', '-' })[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius); - return radius; - } - - // No corners - matches the RoundedCorner default. - return 0; - } - /// - /// Returns a either true or false. + /// Returns a value indicating whether to round the given corner. /// - /// - /// The corner. + /// + /// The collection of query parameters. /// - /// - /// The input string containing the value to parse. + /// + /// The parameter key. /// /// /// The correct true or false. /// - private bool ParseCorner(Regex corner, string input) + private bool ParseCorner(NameValueCollection queryCollection, string key) { - foreach (Match match in corner.Matches(input)) - { - // Split on corner- - bool cornerRound; - bool.TryParse(match.Value.Split(new[] { '=', '-' })[1], out cornerRound); - return cornerRound; - } - - // No corners - matches the RoundedCorner default. - return true; + return queryCollection[key] == null || QueryParamParser.Instance.ParseValue(queryCollection[key]); } - #endregion } } diff --git a/src/ImageProcessor.Web/Processors/Saturation.cs b/src/ImageProcessor.Web/Processors/Saturation.cs index 02a750ab1..5ed751fd3 100644 --- a/src/ImageProcessor.Web/Processors/Saturation.cs +++ b/src/ImageProcessor.Web/Processors/Saturation.cs @@ -10,22 +10,23 @@ namespace ImageProcessor.Web.Processors { + using System.Collections.Specialized; using System.Text.RegularExpressions; + using System.Web; + + using ImageProcessor.Imaging.Helpers; using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; /// /// Encapsulates methods to change the saturation component of the image. /// - /// - /// - /// public class Saturation : IWebGraphicsProcessor { /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"saturation=[^&|,]+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"saturation=(-)?\d+", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -65,25 +66,16 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - int percentage = CommonParameterParserUtility.ParseIn100Range(match.Value); - this.Processor.DynamicParameter = percentage; - } - - index += 1; - } + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + int percentage = QueryParamParser.Instance.ParseValue(queryCollection["saturation"]); + percentage = ImageMaths.Clamp(percentage, -100, 100); + this.Processor.DynamicParameter = percentage; } return this.SortOrder; diff --git a/src/ImageProcessor.Web/Processors/Tint.cs b/src/ImageProcessor.Web/Processors/Tint.cs index f8cce6b6e..3cd592878 100644 --- a/src/ImageProcessor.Web/Processors/Tint.cs +++ b/src/ImageProcessor.Web/Processors/Tint.cs @@ -10,7 +10,11 @@ namespace ImageProcessor.Web.Processors { + using System.Collections.Specialized; + using System.Drawing; using System.Text.RegularExpressions; + using System.Web; + using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; @@ -22,7 +26,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"tint=[^&]+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"tint=[^&]", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -59,24 +63,14 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - this.Processor.DynamicParameter = CommonParameterParserUtility.ParseColor(match.Value.Split('=')[1]); - } - - index += 1; - } + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + this.Processor.DynamicParameter = QueryParamParser.Instance.ParseValue(queryCollection["tint"]); } return this.SortOrder; diff --git a/src/ImageProcessor.Web/Processors/Vignette.cs b/src/ImageProcessor.Web/Processors/Vignette.cs index 56b67f6e1..5f025ae32 100644 --- a/src/ImageProcessor.Web/Processors/Vignette.cs +++ b/src/ImageProcessor.Web/Processors/Vignette.cs @@ -10,8 +10,11 @@ namespace ImageProcessor.Web.Processors { + using System.Collections.Specialized; using System.Drawing; using System.Text.RegularExpressions; + using System.Web; + using ImageProcessor.Processors; using ImageProcessor.Web.Helpers; @@ -65,31 +68,20 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - Color color = CommonParameterParserUtility.ParseColor(match.Value.Split('=')[1]); - if (color.Equals(Color.Transparent)) - { - color = Color.Black; - } - - this.Processor.DynamicParameter = color; - } + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + string vignette = queryCollection["vignette"]; + bool doVignette = QueryParamParser.Instance.ParseValue(vignette); + Color color = doVignette + ? Color.Black + : QueryParamParser.Instance.ParseValue(vignette); - index += 1; - } + this.Processor.DynamicParameter = color; } return this.SortOrder; diff --git a/src/ImageProcessor.Web/Processors/Watermark.cs b/src/ImageProcessor.Web/Processors/Watermark.cs index 92afc3228..d6dec4f4d 100644 --- a/src/ImageProcessor.Web/Processors/Watermark.cs +++ b/src/ImageProcessor.Web/Processors/Watermark.cs @@ -10,15 +10,14 @@ namespace ImageProcessor.Web.Processors { + using System.Collections.Specialized; using System.Drawing; using System.Drawing.Text; - using System.Globalization; - using System.Linq; using System.Text.RegularExpressions; + using System.Web; using ImageProcessor.Imaging; using ImageProcessor.Processors; - using ImageProcessor.Web.Extensions; using ImageProcessor.Web.Helpers; /// @@ -29,47 +28,7 @@ namespace ImageProcessor.Web.Processors /// /// The regular expression to search strings for. /// - private static readonly Regex QueryRegex = new Regex(@"watermark=[^&]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the text attribute. - /// - private static readonly Regex TextRegex = new Regex(@"(watermark=[^text-]|text-)[^/:?#\[\]@!$&'()*%\|,;=&]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the position attribute. - /// - private static readonly Regex PositionRegex = new Regex(@"(watermark.position|textposition|[^.](&,=)?position)(=|-)\d+[-,]\d+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font size attribute. - /// - private static readonly Regex FontSizeRegex = new Regex(@"((font)?)size(=|-)\d{1,3}", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font style attribute. - /// - private static readonly Regex FontStyleRegex = new Regex(@"((font)?)style(=|-)(bold|italic|regular|strikeout|underline)", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the font family attribute. - /// - private static readonly Regex FontFamilyRegex = new Regex(@"font(family)?(=|-)[^/:?#\[\]@!$&'()*%\|,;=0-9]+", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the opacity attribute. - /// - private static readonly Regex OpacityRegex = new Regex(@"(watermark.opacity|fontopacity|[^.](&,=)?opacity)(=|-)(?:100|[1-9]?[0-9])", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the shadow attribute. - /// - private static readonly Regex ShadowRegex = new Regex(@"((text|font|drop)?)shadow(=|-)true", RegexOptions.Compiled); - - /// - /// The regular expression to search strings for the color attribute. - /// - private static readonly Regex ColorRegex = new Regex(@"color(=|-)[^&]+", RegexOptions.Compiled); + private static readonly Regex QueryRegex = new Regex(@"watermark=", RegexOptions.Compiled); /// /// Initializes a new instance of the class. @@ -111,38 +70,27 @@ namespace ImageProcessor.Web.Processors /// public int MatchRegexIndex(string queryString) { - int index = 0; - - // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; + Match match = this.RegexPattern.Match(queryString); - foreach (Match match in this.RegexPattern.Matches(queryString)) + if (match.Success) { - if (match.Success) + this.SortOrder = match.Index; + NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); + TextLayer textLayer = new TextLayer { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - - TextLayer textLayer = new TextLayer - { - Text = this.ParseText(queryString), - Position = this.ParsePosition(queryString), - FontColor = this.ParseColor(queryString), - FontSize = this.ParseFontSize(queryString), - FontFamily = this.ParseFontFamily(queryString), - Style = this.ParseFontStyle(queryString), - DropShadow = this.ParseDropShadow(queryString) - }; - - textLayer.Opacity = this.ParseOpacity(queryString, textLayer.FontColor); - - this.Processor.DynamicParameter = textLayer; - } - - index += 1; - } + Text = this.ParseText(queryCollection), + Position = this.ParsePosition(queryCollection), + FontColor = this.ParseColor(queryCollection), + FontSize = this.ParseFontSize(queryCollection), + FontFamily = this.ParseFontFamily(queryCollection), + Style = this.ParseFontStyle(queryCollection), + DropShadow = this.ParseDropShadow(queryCollection) + }; + + textLayer.Opacity = this.ParseOpacity(queryCollection, textLayer.FontColor); + + this.Processor.DynamicParameter = textLayer; } return this.SortOrder; @@ -150,200 +98,135 @@ namespace ImageProcessor.Web.Processors #region Private Methods /// - /// Returns the correct for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// - /// The correct for the given string. + /// The correct . /// - private string ParseText(string input) + private string ParseText(NameValueCollection queryCollection) { - foreach (Match match in TextRegex.Matches(input)) - { - // split on text- - return match.Value.Split(new[] { '=', '-' })[1].Replace("+", " "); - } - - return string.Empty; + return QueryParamParser.Instance.ParseValue(queryCollection["watermark"]); } /// - /// Returns the correct for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// /// The correct /// - private Point? ParsePosition(string input) + private Point? ParsePosition(NameValueCollection queryCollection) { - foreach (Match match in PositionRegex.Matches(input)) - { - // Chop off the leading legacy support '=' - int[] position = match.Value.TrimStart('=').ToPositiveIntegerArray(); - - if (position != null) - { - int x = position[0]; - int y = position[1]; - - return new Point(x, y); - } - } - - return null; + return queryCollection["textposition"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["textposition"]) + : (Point?)null; } /// - /// Returns the correct for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// /// The correct /// - private Color ParseColor(string input) + private Color ParseColor(NameValueCollection queryCollection) { - foreach (Match match in ColorRegex.Matches(input)) - { - string value = match.Value.Split(new[] { '=', '-' })[1]; - Color textColor = CommonParameterParserUtility.ParseColor(value); - if (!textColor.Equals(Color.Transparent)) - { - return textColor; - } - } - - return Color.Black; + return queryCollection["color"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["color"]) + : Color.Black; } /// - /// Returns the correct for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// /// The correct /// - private int ParseFontSize(string input) + private int ParseFontSize(NameValueCollection queryCollection) { - foreach (Match match in FontSizeRegex.Matches(input)) - { - // split on size-value - return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture); - } - - // Matches the default number in TextLayer. - return 48; + return queryCollection["fontsize"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["fontsize"]) + : 48; } /// - /// Returns the correct for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The string containing the respective font style. + /// + /// The of query parameters. /// /// /// The correct /// - private FontStyle ParseFontStyle(string input) + private FontStyle ParseFontStyle(NameValueCollection queryCollection) { - FontStyle fontStyle = FontStyle.Bold; - - foreach (Match match in FontStyleRegex.Matches(input)) - { - // split on style- - switch (match.Value.Split(new[] - { - '=', '-' - })[1]) - { - case "italic": - fontStyle = FontStyle.Italic; - break; - case "regular": - fontStyle = FontStyle.Regular; - break; - case "strikeout": - fontStyle = FontStyle.Strikeout; - break; - case "underline": - fontStyle = FontStyle.Underline; - break; - } - } - - return fontStyle; + return queryCollection["fontstyle"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["fontstyle"]) + : FontStyle.Bold; } /// - /// Returns the correct containing the font family for the given string. + /// Returns the correct for the given parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// - /// The correct containing the font family for the given string. + /// The correct . /// - private FontFamily ParseFontFamily(string input) + private FontFamily ParseFontFamily(NameValueCollection queryCollection) { - foreach (Match match in FontFamilyRegex.Matches(input)) - { - // split on font- - string font = match.Value.Split(new[] { '=', '-' })[1].Replace("+", " "); - - return new FontFamily(font); - } + return queryCollection["fontfamily"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["fontfamily"]) + : new FontFamily(GenericFontFamilies.SansSerif); + } - return new FontFamily(GenericFontFamilies.SansSerif); + /// + /// Returns a value indicating whether the watermark is to have a shadow. + /// + /// + /// The of query parameters. + /// + /// + /// The true if the watermark is to have a shadow; otherwise false. + /// + private bool ParseDropShadow(NameValueCollection queryCollection) + { + return QueryParamParser.Instance.ParseValue(queryCollection["dropshadow"]); } /// - /// Returns the correct containing the opacity for the given string. + /// Returns the correct containing the opacity for the parameter collection. /// - /// - /// The input string containing the value to parse. + /// + /// The of query parameters. /// /// /// The of the current . /// /// - /// The correct containing the opacity for the given string. + /// The correct . /// - private int ParseOpacity(string input, Color color) + private int ParseOpacity(NameValueCollection queryCollection, Color color) { if (color.A < 255) { return (color.A / 255) * 100; } - foreach (Match match in OpacityRegex.Matches(input)) - { - // Split on opacity- - return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture); - } - - // Full opacity - matches the TextLayer default. - return 100; - } - - /// - /// Returns a value indicating whether the watermark is to have a shadow. - /// - /// - /// The input string containing the value to parse. - /// - /// - /// The true if the watermark is to have a shadow; otherwise false. - /// - private bool ParseDropShadow(string input) - { - return ShadowRegex.Matches(input).Cast().Any(); + return queryCollection["fontopacity"] != null + ? QueryParamParser.Instance.ParseValue(queryCollection["fontopacity"]) + : 100; } #endregion diff --git a/src/TestWebsites/MVC/Views/Home/External.cshtml b/src/TestWebsites/MVC/Views/Home/External.cshtml index 93704628b..0e18af825 100644 --- a/src/TestWebsites/MVC/Views/Home/External.cshtml +++ b/src/TestWebsites/MVC/Views/Home/External.cshtml @@ -5,15 +5,24 @@
+

Current

+ +

Legacy

+

Current

+ +

Legacy

+

Current

+

Legacy

+
diff --git a/src/TestWebsites/MVC/Web.config b/src/TestWebsites/MVC/Web.config index 136c9c7fa..6da269c4c 100644 --- a/src/TestWebsites/MVC/Web.config +++ b/src/TestWebsites/MVC/Web.config @@ -25,6 +25,15 @@ + + + + + + + + +