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);
}
}
}