/// <summary> /// /// </summary> /// <param name="htmlContainer">the container of the html to handle load stylesheet for</param> /// <param name="src">the source of the element to load the stylesheet by</param> /// <param name="attributes">the attributes of the link element</param> public static string LoadStylesheet(HtmlContainer htmlContainer, string src, Dictionary<string, string> attributes) { ArgChecker.AssertArgNotNull(htmlContainer, "htmlContainer"); try { var args = new HtmlStylesheetLoadEventArgs(src, attributes); htmlContainer.RaiseHtmlStylesheetLoadEvent(args); if(args.SetStyleSheet != null) { return args.SetStyleSheet; } else if(args.SetSrc != null) { return LoadStylesheet(htmlContainer, args.SetSrc); } else { return LoadStylesheet(htmlContainer, src); } } catch (Exception ex) { htmlContainer.ReportError(HtmlRenderErrorType.CssParsing, "Exception in handling stylesheet source", ex); return string.Empty; } }
/// <summary> /// Generate css tree by parsing the given html and applying the given css style data on it. /// </summary> /// <param name="html">the html to parse</param> /// <param name="htmlContainer">the html container to use for reference resolve</param> /// <param name="cssData">the css data to use</param> /// <returns>the root of the generated tree</returns> public static CssBox GenerateCssTree(string html, HtmlContainer htmlContainer, ref CssData cssData) { var root = HtmlParser.ParseDocument(html); if (root != null) { root.HtmlContainer = htmlContainer; bool cssDataChanged = false; CascadeStyles(root, htmlContainer, ref cssData, ref cssDataChanged); SetTextSelectionStyle(htmlContainer, cssData); CorrectTextBoxes(root); CorrectImgBoxes(root); CorrectLineBreaksBlocks(root); CorrectInlineBoxesParent(root); CorrectBlockInsideInline(root); CorrectInlineBoxesParent(root); } return root; }
/// <summary> /// Load stylesheet string from given source (file path or uri). /// </summary> /// <param name="htmlContainer">the container of the html to handle load stylesheet for</param> /// <param name="src">the file path or uri to load the stylesheet from</param> /// <returns>the stylesheet string</returns> private static string LoadStylesheet(HtmlContainer htmlContainer, string src) { var uri = CommonUtils.TryGetUri(src); if (uri != null && uri.Scheme != "file") { return LoadStylesheetFromUri(uri); } else { return LoadStylesheetFromFile(htmlContainer, uri != null ? uri.AbsolutePath : src); } }
/// <summary> /// Set image of this image box by analyzing the src attribute.<br/> /// Load the image from inline base64 encoded string.<br/> /// Or from calling property/method on the bridge object that returns image or url to image.<br/> /// Or from file path<br/> /// Or from URI. /// </summary> /// <remarks> /// File path and URI image loading is executed async and after finishing calling <see cref="ImageLoadComplete"/> /// on the main thread and not thread-pool. /// </remarks> /// <param name="htmlContainer">the container of the html to handle load image for</param> /// <param name="src">the source of the image to load</param> /// <param name="attributes">the collection of attributes on the element to use in event</param> /// <returns>the image object (null if failed)</returns> public void LoadImage(HtmlContainer htmlContainer, string src, Dictionary<string, string> attributes) { ArgChecker.AssertArgNotNull(htmlContainer, "htmlContainer"); _htmlContainer = htmlContainer; try { var args = new HtmlImageLoadEventArgs(src, attributes, OnHtmlImageLoadEventCallback); _htmlContainer.RaiseHtmlImageLoadEvent(args); _asyncCallback = true; if (!args.Handled) { if (!string.IsNullOrEmpty(src)) { if (src.StartsWith("data:image", StringComparison.CurrentCultureIgnoreCase)) { _image = GetImageFromData(src); if (_image == null) _htmlContainer.ReportError(HtmlRenderErrorType.Image, "Failed extract image from inline data"); _releaseImageObject = true; ImageLoadComplete(false); } else { SetImageFromPath(src); } } else { ImageLoadComplete(false); } } } catch (Exception ex) { _htmlContainer.ReportError(HtmlRenderErrorType.Image, "Exception in handling image source", ex); ImageLoadComplete(false); } }
static void Main() { using (var bitmap = new Bitmap(300, 200, PixelFormat.Format24bppRgb)) { using (var graphics = Graphics.FromImage(bitmap)) { graphics.Clear(Color.Black); graphics.DrawLine(Pens.Fuchsia, 0,0,300,200); TextRenderer.DrawText(graphics, "TEST", new Font("Arial", 20), new Point(0, 0), Color.FromArgb(50, 0, 255, 0),Color.White); graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; using (var htmlContainer = new HtmlContainer()) { htmlContainer.TextRenderingMethod = TextRenderingMethod.Gdi; htmlContainer.AvoidGeometryAntialias = false; htmlContainer.SetHtml(File.ReadAllText(@"c:\source\html.txt")); htmlContainer.MaxSize = new SizeF(bitmap.Width, bitmap.Height); htmlContainer.PerformLayout(graphics); htmlContainer.PerformPaint(graphics); } } bitmap.Save(@"c:\source\test.png"); } return; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new DemoForm()); // Application.Run(new PerfForm()); // ObfuscateHtml(); }
/// <summary> /// Load the stylesheet from local file by given path. /// </summary> /// <param name="htmlContainer">the container of the html to handle load stylesheet for</param> /// <param name="path">the stylesheet file to load</param> /// <returns>the loaded stylesheet string</returns> private static string LoadStylesheetFromFile(HtmlContainer htmlContainer, string path) { var fileInfo = CommonUtils.TryGetFileInfo(path); if (fileInfo != null) { if (fileInfo.Exists) { using (var sr = new StreamReader(fileInfo.FullName)) { return sr.ReadToEnd(); } } else { htmlContainer.ReportError(HtmlRenderErrorType.CssParsing, "No stylesheet found by path: " + path); } } else { htmlContainer.ReportError(HtmlRenderErrorType.CssParsing, "Failed load image, invalid source: " + path); } return string.Empty; }
/// <summary> /// Set the selected text style (selection text color and background color). /// </summary> /// <param name="htmlContainer"> </param> /// <param name="cssData">the style data</param> private static void SetTextSelectionStyle(HtmlContainer htmlContainer, CssData cssData) { htmlContainer.SelectionForeColor = Color.Empty; htmlContainer.SelectionBackColor = Color.Empty; if (cssData.ContainsCssBlock("::selection")) { var blocks = cssData.GetCssBlock("::selection"); foreach (var block in blocks) { if (block.Properties.ContainsKey("color")) htmlContainer.SelectionForeColor = CssValueParser.GetActualColor(block.Properties["color"]); if (block.Properties.ContainsKey("background-color")) htmlContainer.SelectionBackColor = CssValueParser.GetActualColor(block.Properties["background-color"]); } } }
/// <summary> /// Applies style to all boxes in the tree.<br/> /// If the html tag has style defined for each apply that style to the css box of the tag.<br/> /// If the html tag has "class" attribute and the class name has style defined apply that style on the tag css box.<br/> /// If the html tag has "style" attribute parse it and apply the parsed style on the tag css box.<br/> /// If the html tag is "style" tag parse it content and add to the css data for all future tags parsing.<br/> /// If the html tag is "link" that point to style data parse it content and add to the css data for all future tags parsing.<br/> /// </summary> /// <param name="box"></param> /// <param name="htmlContainer">the html container to use for reference resolve</param> /// <param name="cssData"> </param> /// <param name="cssDataChanged">check if the css data has been modified by the handled html not to change the base css data</param> private static void CascadeStyles(CssBox box, HtmlContainer htmlContainer, ref CssData cssData, ref bool cssDataChanged) { box.InheritStyle(); if (box.HtmlTag != null) { // try assign style using the html element tag AssignCssBlocks(box, cssData, box.HtmlTag.Name); // try assign style using the "class" attribute of the html element if (box.HtmlTag.HasAttribute("class")) { AssignClassCssBlocks(box, cssData); } // try assign style using the "id" attribute of the html element if (box.HtmlTag.HasAttribute("id")) { var id = box.HtmlTag.TryGetAttribute("id"); AssignCssBlocks(box, cssData, "#" + id); } TranslateAttributes(box.HtmlTag, box); // Check for the style="" attribute if (box.HtmlTag.HasAttribute("style")) { var block = CssParser.ParseCssBlock(box.HtmlTag.Name, box.HtmlTag.TryGetAttribute("style")); AssignCssBlock(box, block); } // Check for the <style> tag if (box.HtmlTag.Name.Equals("style", StringComparison.CurrentCultureIgnoreCase) && box.Boxes.Count == 1) { CloneCssData(ref cssData, ref cssDataChanged); CssParser.ParseStyleSheet(cssData, box.Boxes[0].Text.CutSubstring()); } // Check for the <link rel=stylesheet> tag if (box.HtmlTag.Name.Equals("link", StringComparison.CurrentCultureIgnoreCase) && box.GetAttribute("rel", string.Empty).Equals("stylesheet", StringComparison.CurrentCultureIgnoreCase)) { CloneCssData(ref cssData, ref cssDataChanged); var styleSheet = StylesheetLoadHelper.LoadStylesheet(htmlContainer, box.GetAttribute("href", string.Empty), box.HtmlTag.Attributes); CssParser.ParseStyleSheet(cssData, styleSheet); } } // cascade text decoration only to boxes that actually have text so it will be handled correctly. if (box.TextDecoration != String.Empty && box.Text == null) { foreach (var childBox in box.Boxes) childBox.TextDecoration = box.TextDecoration; box.TextDecoration = string.Empty; } foreach (var childBox in box.Boxes) { CascadeStyles(childBox, htmlContainer, ref cssData, ref cssDataChanged); } }
/// <summary> /// Init. /// </summary> /// <param name="selectionHandler">the selection handler linked to the context menu handler</param> /// <param name="htmlContainer">the html container the handler is on</param> public ContextMenuHandler(SelectionHandler selectionHandler, HtmlContainer htmlContainer) { ArgChecker.AssertArgNotNull(selectionHandler, "selectionHandler"); ArgChecker.AssertArgNotNull(htmlContainer, "htmlContainer"); _selectionHandler = selectionHandler; _htmlContainer = htmlContainer; }