123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- 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;
- // <b>, <i>, <u>
- if (i + 3 <= text.Length)
- {
- match = true;
- tag = text.Substring(i, 3).ToLower();
- if (tag == "<b>")
- newStyle.FontStyle |= System.Drawing.FontStyle.Bold;
- else if (tag == "<i>")
- newStyle.FontStyle |= System.Drawing.FontStyle.Italic;
- else if (tag == "<u>")
- newStyle.FontStyle |= System.Drawing.FontStyle.Underline;
- else
- match = false;
- if (match)
- i += 3;
- }
- // </b>, </i>, </u>
- if (!match && i + 4 <= text.Length && text[i + 1] == '/')
- {
- match = true;
- tag = text.Substring(i, 4).ToLower();
- if (tag == "</b>")
- newStyle.FontStyle &= ~System.Drawing.FontStyle.Bold;
- else if (tag == "</i>")
- newStyle.FontStyle &= ~System.Drawing.FontStyle.Italic;
- else if (tag == "</u>")
- newStyle.FontStyle &= ~System.Drawing.FontStyle.Underline;
- else
- match = false;
- if (match)
- i += 4;
- }
- // <sub>, <sup>, <font
- if (!match && i + 5 <= text.Length)
- {
- match = true;
- tag = text.Substring(i, 5).ToLower();
- if (tag == "<sub>")
- newStyle.BaseLine = BaseLine.Subscript;
- else if (tag == "<sup>")
- newStyle.BaseLine = BaseLine.Superscript;
- else if (tag == "<font")
- {
- //try to found end of open tag
- int right = text.IndexOf('>', 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;
- }
- // </sub>, </sup>
- if (!match && i + 6 <= text.Length && text[i + 1] == '/')
- {
- match = true;
- tag = text.Substring(i, 6).ToLower();
- if (tag == "</sub>")
- newStyle.BaseLine = BaseLine.Normal;
- else if (tag == "</sup>")
- newStyle.BaseLine = BaseLine.Normal;
- else
- match = false;
- if (match)
- i += 6;
- }
- // <strike>
- if (!match && i + 8 <= text.Length && text.Substring(i, 8).ToLower() == "<strike>")
- {
- newStyle.FontStyle |= System.Drawing.FontStyle.Strikeout;
- match = true;
- i += 8;
- }
- // </strike>
- if (!match && i + 9 <= text.Length && text.Substring(i, 9).ToLower() == "</strike>")
- {
- newStyle.FontStyle &= ~System.Drawing.FontStyle.Strikeout;
- match = true;
- i += 9;
- }
- // </font>
- if (!match && i + 7 <= text.Length && text.Substring(i, 7).ToLower() == "</font>")
- {
- newStyle = new StyleDescriptor(defaultStyle);
- match = true;
- i += 7;
- }
- // <br/>
- if (!match && i + 5 <= text.Length && text.Substring(i, 5).ToLower() == "<br/>")
- {
- 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);
- }
- }
- }
- }
- }
|