using FastReport.Utils; using System.Drawing; using System.Globalization; using System.Text; using System.Windows.Forms; namespace FastReport.Controls { internal class HtmlDescriptionTextBlock : System.Windows.Controls.TextBlock { public System.Windows.Media.ImageSource Image { get; set; } public string Description { get; set; } public void ParseDescription() { Inlines.Clear(); if (Image != null) { Inlines.Add( new System.Windows.Documents.InlineUIContainer( new System.Windows.Controls.Image() { Source = Image, Width = 16, Height = 16, Margin = new System.Windows.Thickness(0, 0, 4, 0) }) { BaselineAlignment = System.Windows.BaselineAlignment.Center }); } ConvertHtml(Description, new StyleDescriptor(DrawUtils.DefaultFont)); } private enum BaseLine { Normal, Subscript, Superscript } private class StyleDescriptor { public string FontName; public float FontSize; public FontStyle FontStyle; public Color Color; public BaseLine BaseLine; public StyleDescriptor(string fontName, float fontSize, FontStyle fontStyle, Color color, BaseLine baseLine) { FontName = fontName; FontStyle = fontStyle; FontSize = fontSize; Color = color; BaseLine = baseLine; } public StyleDescriptor(Font font) : this(font.Name, font.Size, FontStyle.Regular, Color.Black, BaseLine.Normal) { } public StyleDescriptor(StyleDescriptor other) : this(other.FontName, other.FontSize, other.FontStyle, other.Color, other.BaseLine) { } } private void AddRun(string text, StyleDescriptor s) { var run = new System.Windows.Documents.Run(); run.Text = text; Helper.SetFont(s.FontName, s.FontSize, s.FontStyle, Helper.GetDpiScale(this), out var family, out var size, out var style, out var weight, out var deco); run.FontFamily = family; run.FontSize = size; run.FontStyle = style; run.FontWeight = weight; run.TextDecorations = deco; run.Foreground = Helper.GetBrush(s.Color); Inlines.Add(run); } private void AddLineBreak() { Inlines.Add(new System.Windows.Documents.LineBreak()); } private void ConvertHtml(string text, StyleDescriptor defaultStyle) { StringBuilder currentWord = new StringBuilder(100); StyleDescriptor style = new StyleDescriptor(defaultStyle); for (int i = 0; i < text.Length; i++) { char lastChar = text[i]; if (lastChar == '<') { // probably html tag StyleDescriptor newStyle = new StyleDescriptor(style); string tag = ""; bool match = false; // , , if (i + 3 <= text.Length) { match = true; tag = text.Substring(i, 3).ToLower(); if (tag == "") newStyle.FontStyle |= System.Drawing.FontStyle.Bold; else if (tag == "") newStyle.FontStyle |= System.Drawing.FontStyle.Italic; else if (tag == "") newStyle.FontStyle |= System.Drawing.FontStyle.Underline; else match = false; if (match) i += 3; } // , , if (!match && i + 4 <= text.Length && text[i + 1] == '/') { match = true; tag = text.Substring(i, 4).ToLower(); if (tag == "") newStyle.FontStyle &= ~System.Drawing.FontStyle.Bold; else if (tag == "") newStyle.FontStyle &= ~System.Drawing.FontStyle.Italic; else if (tag == "") newStyle.FontStyle &= ~System.Drawing.FontStyle.Underline; else match = false; if (match) i += 4; } // , , ") newStyle.BaseLine = BaseLine.Subscript; else if (tag == "") newStyle.BaseLine = BaseLine.Superscript; else if (tag == "', i + 5); if (right <= 0) match = false; else { //found font and parse them string color = null; string face = null; string size = null; int color_ind = text.IndexOf("color=\"", i + 5); if (color_ind < right && color_ind >= 0) { color_ind += 7; int color_end = text.IndexOf("\"", color_ind); if (color_end < right && color_end >= 0) { color = text.Substring(color_ind, color_end - color_ind); } } int face_ind = text.IndexOf("face=\"", i + 5); if (face_ind < right && face_ind >= 0) { face_ind += 6; int face_end = text.IndexOf("\"", face_ind); if (face_end < right && face_end >= 0) { face = text.Substring(face_ind, face_end - face_ind); } } int size_ind = text.IndexOf("size=\"", i + 5); if (size_ind < right && size_ind >= 0) { size_ind += 6; int size_end = text.IndexOf("\"", size_ind); if (size_end < right && size_end >= 0) { size = text.Substring(size_ind, size_end - size_ind); } } if (color != null) { if (color.StartsWith("\"") && color.EndsWith("\"")) color = color.Substring(1, color.Length - 2); if (color.StartsWith("#")) { newStyle.Color = Color.FromArgb((int)(0xFF000000 + uint.Parse(color.Substring(1), NumberStyles.HexNumber))); } else { newStyle.Color = Color.FromName(color); } } if (face != null) newStyle.FontName = face; if (size != null) { try { size = size.Trim(' '); newStyle.FontSize = (float)Converter.FromString(typeof(float), size); } catch { } } i = right - 4; } } else match = false; if (match) i += 5; } // , if (!match && i + 6 <= text.Length && text[i + 1] == '/') { match = true; tag = text.Substring(i, 6).ToLower(); if (tag == "") newStyle.BaseLine = BaseLine.Normal; else if (tag == "") newStyle.BaseLine = BaseLine.Normal; else match = false; if (match) i += 6; } // if (!match && i + 8 <= text.Length && text.Substring(i, 8).ToLower() == "") { newStyle.FontStyle |= System.Drawing.FontStyle.Strikeout; match = true; i += 8; } // if (!match && i + 9 <= text.Length && text.Substring(i, 9).ToLower() == "") { newStyle.FontStyle &= ~System.Drawing.FontStyle.Strikeout; match = true; i += 9; } // if (!match && i + 7 <= text.Length && text.Substring(i, 7).ToLower() == "") { newStyle = new StyleDescriptor(defaultStyle); match = true; i += 7; } //
if (!match && i + 5 <= text.Length && text.Substring(i, 5).ToLower() == "
") { i += 5 - 1; lastChar = '\n'; } if (match) { if (currentWord.Length != 0) { // finish the word AddRun(currentWord.ToString(), style); } currentWord.Clear(); style = newStyle; i--; continue; } } if (lastChar == '&') { if (Converter.FromHtmlEntities(text, ref i, currentWord)) { if (i >= text.Length - 1) { AddRun(currentWord.ToString(), style); break; } else { continue; } } } // skip r, handle n if (lastChar == '\r') continue; if (lastChar == '\n') { if (currentWord.Length != 0) AddRun(currentWord.ToString(), style); currentWord.Clear(); AddLineBreak(); continue; } currentWord.Append(lastChar); if (i == text.Length - 1) { // finish the last word if (currentWord.Length != 0) AddRun(currentWord.ToString(), style); } } } } }