using System; using System.Collections.Generic; using System.Text; using UnityEngine; namespace FairyGUI.Utils { /// /// /// public class HtmlParser { public static HtmlParser inst = new HtmlParser(); protected class TextFormat2 : TextFormat { public bool colorChanged; } protected List _textFormatStack; protected int _textFormatStackTop; protected TextFormat2 _format; protected List _elements; protected HtmlParseOptions _defaultOptions; static List sHelperList1 = new List(); static List sHelperList2 = new List(); public HtmlParser() { _textFormatStack = new List(); _format = new TextFormat2(); _defaultOptions = new HtmlParseOptions(); } virtual public void Parse(string aSource, TextFormat defaultFormat, List elements, HtmlParseOptions parseOptions) { if (parseOptions == null) parseOptions = _defaultOptions; _elements = elements; _textFormatStackTop = 0; _format.CopyFrom(defaultFormat); _format.colorChanged = false; int skipText = 0; bool ignoreWhiteSpace = parseOptions.ignoreWhiteSpace; bool skipNextCR = false; string text; XMLIterator.Begin(aSource, true); while (XMLIterator.NextTag()) { if (skipText == 0) { text = XMLIterator.GetText(ignoreWhiteSpace); if (text.Length > 0) { if (skipNextCR && text[0] == '\n') text = text.Substring(1); AppendText(text); } } skipNextCR = false; switch (XMLIterator.tagName) { case "b": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.bold = true; } else PopTextFormat(); break; case "i": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.italic = true; } else PopTextFormat(); break; case "u": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.underline = true; } else PopTextFormat(); break; case "strike": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.strikethrough = true; } else PopTextFormat(); break; case "sub": { if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.specialStyle = TextFormat.SpecialStyle.Subscript; } else PopTextFormat(); } break; case "sup": { if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.specialStyle = TextFormat.SpecialStyle.Superscript; } else PopTextFormat(); } break; case "font": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.size = XMLIterator.GetAttributeInt("size", _format.size); string color = XMLIterator.GetAttribute("color"); if (color != null) { string[] parts = color.Split(','); if (parts.Length == 1) { _format.color = ToolSet.ConvertFromHtmlColor(color); _format.gradientColor = null; _format.colorChanged = true; } else { if (_format.gradientColor == null) _format.gradientColor = new Color32[4]; _format.gradientColor[0] = ToolSet.ConvertFromHtmlColor(parts[0]); _format.gradientColor[1] = ToolSet.ConvertFromHtmlColor(parts[1]); if (parts.Length > 2) { _format.gradientColor[2] = ToolSet.ConvertFromHtmlColor(parts[2]); if (parts.Length > 3) _format.gradientColor[3] = ToolSet.ConvertFromHtmlColor(parts[3]); else _format.gradientColor[3] = _format.gradientColor[2]; } else { _format.gradientColor[2] = _format.gradientColor[0]; _format.gradientColor[3] = _format.gradientColor[1]; } } } } else if (XMLIterator.tagType == XMLTagType.End) PopTextFormat(); break; case "br": AppendText("\n"); break; case "img": if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void) { HtmlElement element = HtmlElement.GetElement(HtmlElementType.Image); element.FetchAttributes(); element.name = element.GetString("name"); element.format.align = _format.align; _elements.Add(element); } break; case "a": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); _format.underline = _format.underline || parseOptions.linkUnderline; if (!_format.colorChanged && parseOptions.linkColor.a != 0) _format.color = parseOptions.linkColor; HtmlElement element = HtmlElement.GetElement(HtmlElementType.Link); element.FetchAttributes(); element.name = element.GetString("name"); element.format.align = _format.align; _elements.Add(element); } else if (XMLIterator.tagType == XMLTagType.End) { PopTextFormat(); HtmlElement element = HtmlElement.GetElement(HtmlElementType.LinkEnd); _elements.Add(element); } break; case "input": { HtmlElement element = HtmlElement.GetElement(HtmlElementType.Input); element.FetchAttributes(); element.name = element.GetString("name"); element.format.CopyFrom(_format); _elements.Add(element); } break; case "select": { if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void) { HtmlElement element = HtmlElement.GetElement(HtmlElementType.Select); element.FetchAttributes(); if (XMLIterator.tagType == XMLTagType.Start) { sHelperList1.Clear(); sHelperList2.Clear(); while (XMLIterator.NextTag()) { if (XMLIterator.tagName == "select") break; if (XMLIterator.tagName == "option") { if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void) sHelperList2.Add(XMLIterator.GetAttribute("value", string.Empty)); else sHelperList1.Add(XMLIterator.GetText()); } } element.Set("items", sHelperList1.ToArray()); element.Set("values", sHelperList2.ToArray()); } element.name = element.GetString("name"); element.format.CopyFrom(_format); _elements.Add(element); } } break; case "p": if (XMLIterator.tagType == XMLTagType.Start) { PushTextFormat(); string align = XMLIterator.GetAttribute("align"); switch (align) { case "center": _format.align = AlignType.Center; break; case "right": _format.align = AlignType.Right; break; } if (!IsNewLine()) AppendText("\n"); } else if (XMLIterator.tagType == XMLTagType.End) { AppendText("\n"); skipNextCR = true; PopTextFormat(); } break; case "ui": case "div": case "li": if (XMLIterator.tagType == XMLTagType.Start) { if (!IsNewLine()) AppendText("\n"); } else { AppendText("\n"); skipNextCR = true; } break; case "html": case "body": //full html ignoreWhiteSpace = true; break; case "head": case "style": case "script": case "form": if (XMLIterator.tagType == XMLTagType.Start) skipText++; else if (XMLIterator.tagType == XMLTagType.End) skipText--; break; } } if (skipText == 0) { text = XMLIterator.GetText(ignoreWhiteSpace); if (text.Length > 0) { if (skipNextCR && text[0] == '\n') text = text.Substring(1); AppendText(text); } } _elements = null; } protected void PushTextFormat() { TextFormat2 tf; if (_textFormatStack.Count <= _textFormatStackTop) { tf = new TextFormat2(); _textFormatStack.Add(tf); } else tf = _textFormatStack[_textFormatStackTop]; tf.CopyFrom(_format); tf.colorChanged = _format.colorChanged; _textFormatStackTop++; } protected void PopTextFormat() { if (_textFormatStackTop > 0) { TextFormat2 tf = _textFormatStack[_textFormatStackTop - 1]; _format.CopyFrom(tf); _format.colorChanged = tf.colorChanged; _textFormatStackTop--; } } protected bool IsNewLine() { if (_elements.Count > 0) { HtmlElement element = _elements[_elements.Count - 1]; if (element != null && element.type == HtmlElementType.Text) return element.text.EndsWith("\n"); else return false; } return true; } protected void AppendText(string text) { HtmlElement element; if (_elements.Count > 0) { element = _elements[_elements.Count - 1]; if (element.type == HtmlElementType.Text && element.format.EqualStyle(_format)) { element.text += text; return; } } element = HtmlElement.GetElement(HtmlElementType.Text); element.text = text; element.format.CopyFrom(_format); _elements.Add(element); } } }