private static void GetGeneralProperties(ICssStyleDeclaration csd, IStyle style) { if (csd.GetPropertyValue("zoom-min-visible") != string.Empty) style.MinVisible = double.Parse(csd.GetPropertyValue("zoom-min-visible")); if (csd.GetPropertyValue("zoom-max-visible") != string.Empty) style.MaxVisible = double.Parse(csd.GetPropertyValue("zoom-max-visible")); }
static StyleRange ExtractStyle(ICssStyleDeclaration style) { var mappedStyle = new StyleRange(); string cssColor = null; try { cssColor = style?.GetPropertyValue("color"); mappedStyle.Color = ParseColor(cssColor); } catch (NullReferenceException) { } try { string fontWeight = null; fontWeight = style?.GetPropertyValue("font-weight"); mappedStyle.Bold = (!string.IsNullOrEmpty(fontWeight) && fontWeight == "bold"); } catch (NullReferenceException) { } try { string fontStyle = null; fontStyle = style?.GetPropertyValue("font-style"); mappedStyle.Italic = (!string.IsNullOrEmpty(fontStyle) && fontStyle == "italic"); } catch (NullReferenceException) { } return(mappedStyle); }
private static void GetGeneralProperties(ICssStyleDeclaration csd, IStyle style) { if (csd.GetPropertyValue("zoom-min-visible") != string.Empty) { style.MinVisible = double.Parse(csd.GetPropertyValue("zoom-min-visible")); } if (csd.GetPropertyValue("zoom-max-visible") != string.Empty) { style.MaxVisible = double.Parse(csd.GetPropertyValue("zoom-max-visible")); } }
private static IStyle GetVectorStyle(ICssStyleDeclaration csd) { // VectorStyle object rebuild. Deserializes: // border-color Line.Color // border-width Line.Width // outline-color Outline.Color // outline-width Outline.Width // outline-style EnableOutline // background-color Fill VectorStyle vStyle = new VectorStyle(); if (csd.GetPropertyValue("border-color") != string.Empty) vStyle.Line.Color = GetColorFromCss(csd, "border-color"); if (csd.GetPropertyValue("border-width") != string.Empty) vStyle.Line.Width = float.Parse(csd.GetPropertyValue("border-width")); if (csd.GetPropertyValue("outline-color") != string.Empty) vStyle.Outline.Color = GetColorFromCss(csd, "outline-color"); if (csd.GetPropertyValue("outline-width") != string.Empty) vStyle.Outline.Width = float.Parse(csd.GetPropertyValue("outline-width")); if (csd.GetPropertyValue("outline-style") != string.Empty) vStyle.EnableOutline = (csd.GetPropertyValue("outline-style") == "enabled" ? true : false); if (csd.GetPropertyValue("background-color") != string.Empty) vStyle.Fill = new SolidBrush(GetColorFromCss(csd, "background-color")); vStyle.Line.EndCap = (LineCap)Enum.Parse(typeof(LineCap), csd.GetPropertyValue(endcapName)); if (csd.GetPropertyValue("geometry-type") != string.Empty) { vStyle.GeometryType = GetGeometryTypeFromCssString(csd); } if (csd.GetPropertyValue("symbol-shape") != string.Empty) { vStyle.Shape = (VectorStyle.ShapeType?) Enum.Parse(typeof(VectorStyle.ShapeType), csd.GetPropertyValue("symbol-shape")); } if (csd.GetPropertyValue("symbol") != string.Empty) { // From a Codepage 1251-encoded string, convert to bytes and next to a Bitmap representing the symbol byte[] bytes = Convert.FromBase64String(csd.GetPropertyValue("symbol")); vStyle.Symbol = (Bitmap)TypeDescriptor.GetConverter(typeof(Bitmap)).ConvertFrom(bytes); } return vStyle; }
public void TestStyleMultipleWithSame() { CssXmlElement elm = getElm("<a style='foo:bar; kalle:roffe;foo:newvalue' />", "", "a") as CssXmlElement; ICssStyleDeclaration csd = elm.Style; if (!csd.CssText.Equals("kalle:roffe;foo:newvalue;") && !csd.CssText.Equals("foo:newvalue;kalle:roffe;")) { Assert.Fail(); } Assert.AreEqual(2, csd.Length); Assert.AreEqual("newvalue", csd.GetPropertyValue("foo")); }
private static Color GetColorFromCss(ICssStyleDeclaration csd, string propertyName) { string property = csd.GetPropertyValue(propertyName); string [] components = property.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); Color color; if (components[0].Contains("#")) { color = Color.FromArgb(int.Parse(components[1])); } else { color = Color.FromName(components[0]); } return(color); }
private static Type GetGeometryTypeFromCssString(ICssStyleDeclaration csd) { string property = csd.GetPropertyValue("geometry-type"); if (property == "LineString") { return(typeof(ILineString)); } if (property == "Polygon") { return(typeof(IPolygon)); } if (property == "Point") { return(typeof(IPoint)); } return(new VectorStyle().GeometryType); }
public virtual string GetComputedStringValue(string propertyName, string pseudoElt) { ICssStyleDeclaration csd = GetComputedStyle(pseudoElt); return(csd.GetPropertyValue(propertyName)); }
private static IStyle GetVectorStyle(ICssStyleDeclaration csd) { // VectorStyle object rebuild. Deserializes: // border-color Line.Color // border-width Line.Width // outline-color Outline.Color // outline-width Outline.Width // outline-style EnableOutline // background-color Fill VectorStyle vStyle = new VectorStyle(); if (csd.GetPropertyValue("border-color") != string.Empty) { vStyle.Line.Color = GetColorFromCss(csd, "border-color"); } if (csd.GetPropertyValue("border-width") != string.Empty) { vStyle.Line.Width = float.Parse(csd.GetPropertyValue("border-width")); } if (csd.GetPropertyValue("outline-color") != string.Empty) { vStyle.Outline.Color = GetColorFromCss(csd, "outline-color"); } if (csd.GetPropertyValue("outline-width") != string.Empty) { vStyle.Outline.Width = float.Parse(csd.GetPropertyValue("outline-width")); } if (csd.GetPropertyValue("outline-style") != string.Empty) { vStyle.EnableOutline = (csd.GetPropertyValue("outline-style") == "enabled" ? true : false); } if (csd.GetPropertyValue("background-color") != string.Empty) { vStyle.Fill = new SolidBrush(GetColorFromCss(csd, "background-color")); } vStyle.Line.EndCap = (LineCap)Enum.Parse(typeof(LineCap), csd.GetPropertyValue(endcapName)); if (csd.GetPropertyValue("geometry-type") != string.Empty) { vStyle.GeometryType = GetGeometryTypeFromCssString(csd); } if (csd.GetPropertyValue("symbol-shape") != string.Empty) { vStyle.Shape = (VectorStyle.ShapeType?)Enum.Parse(typeof(VectorStyle.ShapeType), csd.GetPropertyValue("symbol-shape")); } if (csd.GetPropertyValue("symbol") != string.Empty) { // From a Codepage 1251-encoded string, convert to bytes and next to a Bitmap representing the symbol byte[] bytes = Convert.FromBase64String(csd.GetPropertyValue("symbol")); vStyle.Symbol = (Bitmap)TypeDescriptor.GetConverter(typeof(Bitmap)).ConvertFrom(bytes); } return(vStyle); }
private IStyle GetLabelStyle(ICssStyleDeclaration csd) { // LabelStyle object rebuild. Deserializes: // font-family Font.Family // font-size Font.Size // font-color ForeColor // background-color BackColor // border-color Halo.Color // border-width Halo.Width // padding-horizontal Offset.X // padding-vertical Offset.Y // text-align HorizontalAlignment // vertical-align VerticalAlignment LabelStyle lStyle = new LabelStyle(); string fontFamily = lStyle.Font.FontFamily.Name; float fontSize = lStyle.Font.Size; if (csd.GetPropertyValue("font-family") != string.Empty) { fontFamily = csd.GetPropertyValue("font-family"); } if (csd.GetPropertyValue("font-size") != string.Empty) { fontSize = float.Parse(csd.GetPropertyValue("font-size")); } lStyle.Font = new Font(fontFamily, fontSize); if (csd.GetPropertyValue("font-color") != string.Empty) { lStyle.ForeColor = GetColorFromCss(csd, "font-color"); } if (csd.GetPropertyValue("background-color") != string.Empty) { lStyle.BackColor = new SolidBrush(GetColorFromCss(csd, "back-color")); } Color haloColor = lStyle.Halo.Color; float haloWidth = lStyle.Halo.Width; if (csd.GetPropertyValue("border-color") != string.Empty) { haloColor = GetColorFromCss(csd, "border-color"); } if (csd.GetPropertyValue("border-width") != string.Empty) { haloWidth = float.Parse(csd.GetPropertyValue("border-width")); } lStyle.Halo = new Pen(haloColor, haloWidth); float offsetX = lStyle.Offset.X; float offsetY = lStyle.Offset.Y; if (csd.GetPropertyValue("padding-horizontal") != null) { offsetX = float.Parse(csd.GetPropertyValue("padding-horizontal")); } if (csd.GetPropertyValue("padding-vertical") != null) { offsetY = float.Parse(csd.GetPropertyValue("padding-vertical")); } lStyle.Offset = new PointF(offsetX, offsetY); if (csd.GetPropertyValue("text-align") != null) { lStyle.HorizontalAlignment = (LabelStyle.HorizontalAlignmentEnum)Enum.Parse(typeof(LabelStyle.HorizontalAlignmentEnum), csd.GetPropertyValue("text-align")); } if (csd.GetPropertyValue("vertical-align") != null) { lStyle.VerticalAlignment = (LabelStyle.VerticalAlignmentEnum)Enum.Parse(typeof(LabelStyle.VerticalAlignmentEnum), csd.GetPropertyValue("vertical-align")); } return(lStyle); }
/// <summary> /// Validates all images if they are rotated correctly (when <paramref name="rotate"/> is set /// to <c>true</c>) and fit on the given <paramref name="pageSettings"/>. /// If an image does need to be rotated or does not fit then a local copy is made of /// the <paramref name="inputUri"/> file. /// </summary> /// <param name="inputUri">The uri of the webpage</param> /// <param name="resize">When set to <c>true</c> then an image is resized when needed</param> /// <param name="rotate">When set to <c>true</c> then the EXIF information of an /// image is read and when needed the image is automatic rotated</param> /// <param name="pageSettings"><see cref="PageSettings"/></param> /// <param name="outputUri">The outputUri when this method returns <c>true</c> otherwise /// <c>null</c> is returned</param> /// <param name="urlBlacklist">A list of URL's that need to be blocked (use * as a wildcard)</param> /// <param name="safeUrls">A list with URL's that are safe to load</param> /// <returns>Returns <c>false</c> when the images dit not fit the page, otherwise <c>true</c></returns> /// <exception cref="WebException">Raised when the webpage from <paramref name="inputUri"/> could not be downloaded</exception> public bool ValidateImages( ConvertUri inputUri, bool resize, bool rotate, PageSettings pageSettings, out ConvertUri outputUri, ref List <string> safeUrls, List <string> urlBlacklist) { outputUri = null; using (var graphics = Graphics.FromHwnd(IntPtr.Zero)) using (var webpage = inputUri.IsFile ? OpenFileStream(inputUri.OriginalString) : OpenDownloadStream(inputUri)) { WriteToLog($"DPI settings for image, x: '{graphics.DpiX}' and y: '{graphics.DpiY}'"); var maxWidth = (pageSettings.PaperWidth - pageSettings.MarginLeft - pageSettings.MarginRight) * graphics.DpiX; var maxHeight = (pageSettings.PaperHeight - pageSettings.MarginTop - pageSettings.MarginBottom) * graphics.DpiY; string localDirectory = null; if (inputUri.IsFile) { localDirectory = Path.GetDirectoryName(inputUri.OriginalString); } var htmlChanged = false; IConfiguration config; if (_webProxy != null) { WriteToLog($"Using web proxy '{_webProxy.Address}' to download images"); var httpClientHandler = new HttpClientHandler { Proxy = _webProxy, ServerCertificateCustomValidationCallback = (message, certificate, arg1, arg2) => { WriteToLog($"Accepting certificate '{certificate.Subject}', message '{message}'"); return(true); } }; var client = new HttpClient(httpClientHandler); config = Configuration.Default .With(new HttpClientRequester(client)) .WithTemporaryCookies() .WithDefaultLoader() .WithCss(); } else { config = Configuration.Default.WithCss(); } var context = BrowsingContext.New(config); IDocument document; try { // ReSharper disable AccessToDisposedClosure document = inputUri.Encoding != null ? context.OpenAsync(m => m.Content(webpage).Header("Content-Type", $"text/html; charset={inputUri.Encoding.WebName}") .Address(inputUri.ToString())).Result : context.OpenAsync(m => m.Content(webpage).Address(inputUri.ToString())).Result; // ReSharper restore AccessToDisposedClosure } catch (Exception exception) { WriteToLog($"Exception occurred in AngleSharp: {ExceptionHelpers.GetInnerException(exception)}"); return(false); } WriteToLog("Validating all images if they need to be rotated and if they fit the page"); var unchangedImages = new List <IHtmlImageElement>(); var absoluteUri = inputUri.AbsoluteUri.Substring(0, inputUri.AbsoluteUri.LastIndexOf('/') + 1); // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop foreach (var htmlImage in document.Images) { var imageChanged = false; if (string.IsNullOrWhiteSpace(htmlImage.Source)) { WriteToLog($"HTML image tag '{htmlImage.TagName}' has no image source '{htmlImage.Source}'"); continue; } Image image = null; var source = htmlImage.Source.Contains("?") ? htmlImage.Source.Split('?')[0] : htmlImage.Source; var isSafeUrl = safeUrls.Contains(source); var isAbsoluteUri = source.StartsWith(absoluteUri, StringComparison.InvariantCultureIgnoreCase); if (!RegularExpression.IsRegExMatch(urlBlacklist, source, out var matchedPattern) || isAbsoluteUri || isSafeUrl) { if (isAbsoluteUri) { WriteToLog($"The url '{source}' has been allowed because it start with the absolute uri '{absoluteUri}'"); } else if (isSafeUrl) { WriteToLog($"The url '{source}' has been allowed because it is on the safe url list"); } else { WriteToLog($"The url '{source}' has been allowed because it did not match anything on the url blacklist"); } } else { WriteToLog($"The url '{source}' has been blocked by url blacklist pattern '{matchedPattern}'"); continue; } var extension = Path.GetExtension(FileManager.RemoveInvalidFileNameChars(source)); var fileName = GetTempFile(extension); try { // The local width and height attributes always go before css width and height var width = htmlImage.DisplayWidth; var height = htmlImage.DisplayHeight; if (rotate) { image = GetImage(htmlImage.Source, localDirectory); if (image == null) { continue; } if (RotateImageByExifOrientationData(image)) { htmlImage.DisplayWidth = image.Width; htmlImage.DisplayHeight = image.Height; WriteToLog($"Image rotated and saved to location '{fileName}'"); image.Save(fileName); htmlImage.DisplayWidth = image.Width; htmlImage.DisplayHeight = image.Height; htmlImage.SetStyle(string.Empty); var newSrc = new Uri(fileName).ToString(); WriteToLog($"Adding url '{newSrc}' to the safe url list"); safeUrls.Add(newSrc); htmlImage.Source = newSrc; htmlChanged = true; imageChanged = true; } width = image.Width; height = image.Height; } if (resize) { if (height == 0 && width == 0) { ICssStyleDeclaration style = null; try { style = context.Current.GetComputedStyle(htmlImage); } catch (Exception exception) { WriteToLog($"Could not get computed style from html image, exception: '{exception.Message}'"); } if (style != null) { width = ParseValue(style.GetPropertyValue("width")); height = ParseValue(style.GetPropertyValue("height")); } } // If we don't know the image size then get if from the image itself if (width <= 0 || height <= 0) { if (image == null) { image = GetImage(htmlImage.Source, localDirectory); } if (image == null) { continue; } width = image.Width; height = image.Height; } if (width > maxWidth || height > maxHeight) { // If we did not load the image already then load it if (image == null) { image = GetImage(htmlImage.Source, localDirectory); } if (image == null) { continue; } ScaleImage(image, (int)maxWidth, out var newWidth, out var newHeight); WriteToLog($"Image rescaled to width {newWidth} and height {newHeight}"); htmlImage.DisplayWidth = newWidth; htmlImage.DisplayHeight = newHeight; htmlImage.SetStyle(string.Empty); htmlChanged = true; } } } finally { image?.Dispose(); } if (!imageChanged) { unchangedImages.Add(htmlImage); } } if (!htmlChanged) { return(false); } foreach (var unchangedImage in unchangedImages) { using (var image = GetImage(unchangedImage.Source, localDirectory)) { if (image == null) { WriteToLog($"Could not load unchanged image from location '{unchangedImage.Source}'"); continue; } var extension = Path.GetExtension(unchangedImage.Source.Contains("?") ? unchangedImage.Source.Split('?')[0] : unchangedImage.Source); var fileName = GetTempFile(extension); WriteToLog($"Unchanged image saved to location '{fileName}'"); image.Save(fileName); var newSrc = new Uri(fileName).ToString(); safeUrls.Add(newSrc); unchangedImage.Source = newSrc; } } var outputFile = GetTempFile(".htm"); outputUri = new ConvertUri(outputFile, inputUri.Encoding); safeUrls.Add(outputUri.ToString()); try { WriteToLog($"Writing changed webpage to '{outputFile}'"); using (var fileStream = new FileStream(outputFile, FileMode.CreateNew, FileAccess.Write)) { if (inputUri.Encoding != null) { using (var textWriter = new StreamWriter(fileStream, inputUri.Encoding)) document.ToHtml(textWriter, new HtmlMarkupFormatter()); } else { using (var textWriter = new StreamWriter(fileStream)) document.ToHtml(textWriter, new HtmlMarkupFormatter()); } } WriteToLog("Changed webpage written"); return(true); } catch (Exception exception) { WriteToLog($"Could not write new html file '{outputFile}', error: {ExceptionHelpers.GetInnerException(exception)}"); return(false); } } }
private static Color GetColorFromCss(ICssStyleDeclaration csd, string propertyName) { string property = csd.GetPropertyValue(propertyName); string [] components = property.Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries); Color color; if (components[0].Contains("#")) { color = Color.FromArgb(int.Parse(components[1])); } else { color = Color.FromName(components[0]); } return color; }
private static Type GetGeometryTypeFromCssString(ICssStyleDeclaration csd) { string property = csd.GetPropertyValue("geometry-type"); if (property == "LineString") { return typeof(ILineString); } if (property == "Polygon") { return typeof(IPolygon); } if (property == "Point") { return typeof(IPoint); } return new VectorStyle().GeometryType; }
private IStyle GetLabelStyle(ICssStyleDeclaration csd) { // LabelStyle object rebuild. Deserializes: // font-family Font.Family // font-size Font.Size // font-color ForeColor // background-color BackColor // border-color Halo.Color // border-width Halo.Width // padding-horizontal Offset.X // padding-vertical Offset.Y // text-align HorizontalAlignment // vertical-align VerticalAlignment LabelStyle lStyle =new LabelStyle(); string fontFamily = lStyle.Font.FontFamily.Name; float fontSize = lStyle.Font.Size; if (csd.GetPropertyValue("font-family") != string.Empty) fontFamily = csd.GetPropertyValue("font-family"); if (csd.GetPropertyValue("font-size") != string.Empty) fontSize = float.Parse(csd.GetPropertyValue("font-size")); lStyle.Font = new Font(fontFamily, fontSize); if (csd.GetPropertyValue("font-color") != string.Empty) lStyle.ForeColor = GetColorFromCss(csd, "font-color"); if (csd.GetPropertyValue("background-color") != string.Empty) lStyle.BackColor = new SolidBrush(GetColorFromCss(csd, "back-color")); Color haloColor = lStyle.Halo.Color; float haloWidth = lStyle.Halo.Width; if (csd.GetPropertyValue("border-color") != string.Empty) haloColor = GetColorFromCss(csd, "border-color"); if (csd.GetPropertyValue("border-width") != string.Empty) haloWidth = float.Parse(csd.GetPropertyValue("border-width")); lStyle.Halo = new Pen(haloColor, haloWidth); float offsetX = lStyle.Offset.X; float offsetY = lStyle.Offset.Y; if (csd.GetPropertyValue("padding-horizontal") != null) offsetX = float.Parse(csd.GetPropertyValue("padding-horizontal")); if (csd.GetPropertyValue("padding-vertical") != null) offsetY = float.Parse(csd.GetPropertyValue("padding-vertical")); lStyle.Offset = new PointF(offsetX, offsetY); if (csd.GetPropertyValue("text-align") != null) lStyle.HorizontalAlignment = (LabelStyle.HorizontalAlignmentEnum)Enum.Parse(typeof(LabelStyle.HorizontalAlignmentEnum), csd.GetPropertyValue("text-align")); if (csd.GetPropertyValue("vertical-align") != null) lStyle.VerticalAlignment = (LabelStyle.VerticalAlignmentEnum)Enum.Parse(typeof(LabelStyle.VerticalAlignmentEnum), csd.GetPropertyValue("vertical-align")); return lStyle; }