HtmlParser.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using UnityEngine;
  5. namespace FairyGUI.Utils
  6. {
  7. /// <summary>
  8. ///
  9. /// </summary>
  10. public class HtmlParser
  11. {
  12. public static HtmlParser inst = new HtmlParser();
  13. protected class TextFormat2 : TextFormat
  14. {
  15. public bool colorChanged;
  16. }
  17. protected List<TextFormat2> _textFormatStack;
  18. protected int _textFormatStackTop;
  19. protected TextFormat2 _format;
  20. protected List<HtmlElement> _elements;
  21. protected HtmlParseOptions _defaultOptions;
  22. static List<string> sHelperList1 = new List<string>();
  23. static List<string> sHelperList2 = new List<string>();
  24. public HtmlParser()
  25. {
  26. _textFormatStack = new List<TextFormat2>();
  27. _format = new TextFormat2();
  28. _defaultOptions = new HtmlParseOptions();
  29. }
  30. virtual public void Parse(string aSource, TextFormat defaultFormat, List<HtmlElement> elements, HtmlParseOptions parseOptions)
  31. {
  32. if (parseOptions == null)
  33. parseOptions = _defaultOptions;
  34. _elements = elements;
  35. _textFormatStackTop = 0;
  36. _format.CopyFrom(defaultFormat);
  37. _format.colorChanged = false;
  38. int skipText = 0;
  39. bool ignoreWhiteSpace = parseOptions.ignoreWhiteSpace;
  40. bool skipNextCR = false;
  41. string text;
  42. XMLIterator.Begin(aSource, true);
  43. while (XMLIterator.NextTag())
  44. {
  45. if (skipText == 0)
  46. {
  47. text = XMLIterator.GetText(ignoreWhiteSpace);
  48. if (text.Length > 0)
  49. {
  50. if (skipNextCR && text[0] == '\n')
  51. text = text.Substring(1);
  52. AppendText(text);
  53. }
  54. }
  55. skipNextCR = false;
  56. switch (XMLIterator.tagName)
  57. {
  58. case "b":
  59. if (XMLIterator.tagType == XMLTagType.Start)
  60. {
  61. PushTextFormat();
  62. _format.bold = true;
  63. }
  64. else
  65. PopTextFormat();
  66. break;
  67. case "i":
  68. if (XMLIterator.tagType == XMLTagType.Start)
  69. {
  70. PushTextFormat();
  71. _format.italic = true;
  72. }
  73. else
  74. PopTextFormat();
  75. break;
  76. case "u":
  77. if (XMLIterator.tagType == XMLTagType.Start)
  78. {
  79. PushTextFormat();
  80. _format.underline = true;
  81. }
  82. else
  83. PopTextFormat();
  84. break;
  85. case "strike":
  86. if (XMLIterator.tagType == XMLTagType.Start)
  87. {
  88. PushTextFormat();
  89. _format.strikethrough = true;
  90. }
  91. else
  92. PopTextFormat();
  93. break;
  94. case "sub":
  95. {
  96. if (XMLIterator.tagType == XMLTagType.Start)
  97. {
  98. PushTextFormat();
  99. _format.specialStyle = TextFormat.SpecialStyle.Subscript;
  100. }
  101. else
  102. PopTextFormat();
  103. }
  104. break;
  105. case "sup":
  106. {
  107. if (XMLIterator.tagType == XMLTagType.Start)
  108. {
  109. PushTextFormat();
  110. _format.specialStyle = TextFormat.SpecialStyle.Superscript;
  111. }
  112. else
  113. PopTextFormat();
  114. }
  115. break;
  116. case "font":
  117. if (XMLIterator.tagType == XMLTagType.Start)
  118. {
  119. PushTextFormat();
  120. _format.size = XMLIterator.GetAttributeInt("size", _format.size);
  121. string color = XMLIterator.GetAttribute("color");
  122. if (color != null)
  123. {
  124. string[] parts = color.Split(',');
  125. if (parts.Length == 1)
  126. {
  127. _format.color = ToolSet.ConvertFromHtmlColor(color);
  128. _format.gradientColor = null;
  129. _format.colorChanged = true;
  130. }
  131. else
  132. {
  133. if (_format.gradientColor == null)
  134. _format.gradientColor = new Color32[4];
  135. _format.gradientColor[0] = ToolSet.ConvertFromHtmlColor(parts[0]);
  136. _format.gradientColor[1] = ToolSet.ConvertFromHtmlColor(parts[1]);
  137. if (parts.Length > 2)
  138. {
  139. _format.gradientColor[2] = ToolSet.ConvertFromHtmlColor(parts[2]);
  140. if (parts.Length > 3)
  141. _format.gradientColor[3] = ToolSet.ConvertFromHtmlColor(parts[3]);
  142. else
  143. _format.gradientColor[3] = _format.gradientColor[2];
  144. }
  145. else
  146. {
  147. _format.gradientColor[2] = _format.gradientColor[0];
  148. _format.gradientColor[3] = _format.gradientColor[1];
  149. }
  150. }
  151. }
  152. }
  153. else if (XMLIterator.tagType == XMLTagType.End)
  154. PopTextFormat();
  155. break;
  156. case "br":
  157. AppendText("\n");
  158. break;
  159. case "img":
  160. if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
  161. {
  162. HtmlElement element = HtmlElement.GetElement(HtmlElementType.Image);
  163. element.FetchAttributes();
  164. element.name = element.GetString("name");
  165. element.format.align = _format.align;
  166. _elements.Add(element);
  167. }
  168. break;
  169. case "a":
  170. if (XMLIterator.tagType == XMLTagType.Start)
  171. {
  172. PushTextFormat();
  173. _format.underline = _format.underline || parseOptions.linkUnderline;
  174. if (!_format.colorChanged && parseOptions.linkColor.a != 0)
  175. _format.color = parseOptions.linkColor;
  176. HtmlElement element = HtmlElement.GetElement(HtmlElementType.Link);
  177. element.FetchAttributes();
  178. element.name = element.GetString("name");
  179. element.format.align = _format.align;
  180. _elements.Add(element);
  181. }
  182. else if (XMLIterator.tagType == XMLTagType.End)
  183. {
  184. PopTextFormat();
  185. HtmlElement element = HtmlElement.GetElement(HtmlElementType.LinkEnd);
  186. _elements.Add(element);
  187. }
  188. break;
  189. case "input":
  190. {
  191. HtmlElement element = HtmlElement.GetElement(HtmlElementType.Input);
  192. element.FetchAttributes();
  193. element.name = element.GetString("name");
  194. element.format.CopyFrom(_format);
  195. _elements.Add(element);
  196. }
  197. break;
  198. case "select":
  199. {
  200. if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
  201. {
  202. HtmlElement element = HtmlElement.GetElement(HtmlElementType.Select);
  203. element.FetchAttributes();
  204. if (XMLIterator.tagType == XMLTagType.Start)
  205. {
  206. sHelperList1.Clear();
  207. sHelperList2.Clear();
  208. while (XMLIterator.NextTag())
  209. {
  210. if (XMLIterator.tagName == "select")
  211. break;
  212. if (XMLIterator.tagName == "option")
  213. {
  214. if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
  215. sHelperList2.Add(XMLIterator.GetAttribute("value", string.Empty));
  216. else
  217. sHelperList1.Add(XMLIterator.GetText());
  218. }
  219. }
  220. element.Set("items", sHelperList1.ToArray());
  221. element.Set("values", sHelperList2.ToArray());
  222. }
  223. element.name = element.GetString("name");
  224. element.format.CopyFrom(_format);
  225. _elements.Add(element);
  226. }
  227. }
  228. break;
  229. case "p":
  230. if (XMLIterator.tagType == XMLTagType.Start)
  231. {
  232. PushTextFormat();
  233. string align = XMLIterator.GetAttribute("align");
  234. switch (align)
  235. {
  236. case "center":
  237. _format.align = AlignType.Center;
  238. break;
  239. case "right":
  240. _format.align = AlignType.Right;
  241. break;
  242. }
  243. if (!IsNewLine())
  244. AppendText("\n");
  245. }
  246. else if (XMLIterator.tagType == XMLTagType.End)
  247. {
  248. AppendText("\n");
  249. skipNextCR = true;
  250. PopTextFormat();
  251. }
  252. break;
  253. case "ui":
  254. case "div":
  255. case "li":
  256. if (XMLIterator.tagType == XMLTagType.Start)
  257. {
  258. if (!IsNewLine())
  259. AppendText("\n");
  260. }
  261. else
  262. {
  263. AppendText("\n");
  264. skipNextCR = true;
  265. }
  266. break;
  267. case "html":
  268. case "body":
  269. //full html
  270. ignoreWhiteSpace = true;
  271. break;
  272. case "head":
  273. case "style":
  274. case "script":
  275. case "form":
  276. if (XMLIterator.tagType == XMLTagType.Start)
  277. skipText++;
  278. else if (XMLIterator.tagType == XMLTagType.End)
  279. skipText--;
  280. break;
  281. }
  282. }
  283. if (skipText == 0)
  284. {
  285. text = XMLIterator.GetText(ignoreWhiteSpace);
  286. if (text.Length > 0)
  287. {
  288. if (skipNextCR && text[0] == '\n')
  289. text = text.Substring(1);
  290. AppendText(text);
  291. }
  292. }
  293. _elements = null;
  294. }
  295. protected void PushTextFormat()
  296. {
  297. TextFormat2 tf;
  298. if (_textFormatStack.Count <= _textFormatStackTop)
  299. {
  300. tf = new TextFormat2();
  301. _textFormatStack.Add(tf);
  302. }
  303. else
  304. tf = _textFormatStack[_textFormatStackTop];
  305. tf.CopyFrom(_format);
  306. tf.colorChanged = _format.colorChanged;
  307. _textFormatStackTop++;
  308. }
  309. protected void PopTextFormat()
  310. {
  311. if (_textFormatStackTop > 0)
  312. {
  313. TextFormat2 tf = _textFormatStack[_textFormatStackTop - 1];
  314. _format.CopyFrom(tf);
  315. _format.colorChanged = tf.colorChanged;
  316. _textFormatStackTop--;
  317. }
  318. }
  319. protected bool IsNewLine()
  320. {
  321. if (_elements.Count > 0)
  322. {
  323. HtmlElement element = _elements[_elements.Count - 1];
  324. if (element != null && element.type == HtmlElementType.Text)
  325. return element.text.EndsWith("\n");
  326. else
  327. return false;
  328. }
  329. return true;
  330. }
  331. protected void AppendText(string text)
  332. {
  333. HtmlElement element;
  334. if (_elements.Count > 0)
  335. {
  336. element = _elements[_elements.Count - 1];
  337. if (element.type == HtmlElementType.Text && element.format.EqualStyle(_format))
  338. {
  339. element.text += text;
  340. return;
  341. }
  342. }
  343. element = HtmlElement.GetElement(HtmlElementType.Text);
  344. element.text = text;
  345. element.format.CopyFrom(_format);
  346. _elements.Add(element);
  347. }
  348. }
  349. }