123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Xml;
- using CommonLang;
- using CommonUI.Cell.Game;
- using CommonUI.Data;
- using CommonLang.Log;
- using CommonLang.Xml;
- namespace CommonUI.Display.Text
- {
- /// <summary>
- /// 文字字符上的属性
- /// </summary>
- public class TextAttribute : ICloneable
- {
- /// <summary>
- /// 字符颜色 0 表示无特性 (RGBA)
- /// </summary>
- public uint fontColor = 0xffffffff;
- /// <summary>
- /// 子尺寸 0 表示无特性
- /// </summary>
- public float fontSize;
- /// <summary>
- /// 字体名字,空表示无特性
- /// </summary>
- public string fontName;
- /// <summary>
- /// 字体
- /// </summary>
- public FontStyle fontStyle = FontStyle.STYLE_PLAIN;
- public bool underline
- {
- get
- {
- switch (fontStyle)
- {
- case FontStyle.STYLE_BOLD_ITALIC_UNDERLINED:
- case FontStyle.STYLE_ITALIC_UNDERLINED:
- case FontStyle.STYLE_BOLD_UNDERLINED:
- case FontStyle.STYLE_UNDERLINED:
- return true;
- }
- return false;
- }
- set
- {
- if (!value)
- {
- switch (fontStyle)
- {
- case FontStyle.STYLE_BOLD_ITALIC_UNDERLINED:
- fontStyle = FontStyle.STYLE_BOLD_ITALIC;
- break;
- case FontStyle.STYLE_ITALIC_UNDERLINED:
- fontStyle = FontStyle.STYLE_ITALIC;
- break;
- case FontStyle.STYLE_BOLD_UNDERLINED:
- fontStyle = FontStyle.STYLE_BOLD;
- break;
- case FontStyle.STYLE_UNDERLINED:
- fontStyle = FontStyle.STYLE_PLAIN;
- break;
- }
- }
- else
- {
- switch (fontStyle)
- {
- case FontStyle.STYLE_BOLD_ITALIC:
- fontStyle = FontStyle.STYLE_BOLD_ITALIC_UNDERLINED;
- break;
- case FontStyle.STYLE_ITALIC:
- fontStyle = FontStyle.STYLE_ITALIC_UNDERLINED;
- break;
- case FontStyle.STYLE_BOLD:
- fontStyle = FontStyle.STYLE_BOLD_UNDERLINED;
- break;
- case FontStyle.STYLE_PLAIN:
- fontStyle = FontStyle.STYLE_UNDERLINED;
- break;
- }
- }
- }
- }
- /// <summary>
- /// 描边
- /// </summary>
- public TextBorderCount borderCount = TextBorderCount.Null;
- /// <summary>
- /// 描边颜色 (RGBA)
- /// </summary>
- public uint borderColor;
- /// <summary>
- /// 此字符替换成图片,空表示无特性
- /// </summary>
- public string resImage;
- /// <summary>
- /// 图片渲染方式
- /// </summary>
- public ImageZoom resImageZoom;
- /// <summary>
- /// 此字符替换成动画,空表示无特性
- /// </summary>
- public string resSprite;
- /// <summary>
- /// 标记此处可以被点击触发事件,空表示无特性
- /// </summary>
- public string link;
- /// <summary>
- /// 行对齐方式
- /// </summary>
- public RichTextAlignment anchor = RichTextAlignment.taNA;
- /// <summary>
- /// 扩展的自定义渲染部分
- /// </summary>
- public TextDrawable drawable;
- public TextAttribute(
- uint fColor = 0,
- float fSize = 0,
- string fName = null,
- FontStyle fStyle = FontStyle.STYLE_PLAIN,
- RichTextAlignment ta = RichTextAlignment.taNA,
- TextBorderCount bCount = TextBorderCount.Null,
- uint bColor = 0,
- string rImage = null,
- string rSprite = null,
- string pLink = null,
- ImageZoom rImageZoom = null,
- TextDrawable drawable = null)
- {
- this.fontColor = fColor;
- this.fontSize = fSize;
- this.fontName = fName;
- this.fontStyle = fStyle;
- this.anchor = ta;
- this.resImage = rImage;
- this.resImageZoom = rImageZoom;
- this.resSprite = rSprite;
- this.borderCount = bCount;
- this.borderColor = bColor;
- this.link = pLink;
- this.drawable = drawable;
- }
- public TextAttribute(TextAttribute other)
- {
- this.fontColor = other.fontColor;
- this.fontSize = other.fontSize;
- this.fontName = other.fontName;
- this.fontStyle = other.fontStyle;
- this.anchor = other.anchor;
- this.borderCount = other.borderCount;
- this.borderColor = other.borderColor;
- this.resImage = other.resImage;
- this.resImageZoom = CUtils.TryClone(other.resImageZoom);
- this.resSprite = other.resSprite;
- this.link = other.link;
- this.drawable = other.drawable;
- }
- public object Clone()
- {
- return new TextAttribute(this);
- }
- public override bool Equals(object obj)
- {
- if (obj is TextAttribute)
- {
- return this.Equals(obj as TextAttribute);
- }
- return false;
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- public bool Equals(TextAttribute other)
- {
- if (other == this)
- return true;
- if (other == null)
- return false;
- if (this.fontColor != other.fontColor)
- return false;
- if (this.fontSize != other.fontSize)
- return false;
- if (!string.Equals(this.fontName, other.fontName))
- return false;
- if (this.fontStyle != other.fontStyle)
- return false;
- if (this.anchor != other.anchor)
- return false;
- if (this.borderCount != other.borderCount)
- return false;
- if (this.borderColor != other.borderColor)
- return false;
- if (!string.Equals(this.resImage, other.resImage))
- return false;
- if (!string.Equals(this.resSprite, other.resSprite))
- return false;
- if (!ImageZoom.Equals(this.resImageZoom, other.resImageZoom))
- return false;
- if (!string.Equals(this.link, other.link))
- return false;
- if (drawable != null && !drawable.Equals(other.drawable))
- return false;
- if (drawable == null && other.drawable != null)
- {
- return false;
- }
- return true;
- }
- public bool IsValid()
- {
- if (fontColor != 0)
- return true;
- if (fontSize != 0)
- return true;
- if (!string.IsNullOrEmpty(fontName))
- return true;
- if (anchor != RichTextAlignment.taNA)
- return true;
- if (borderCount > 0)
- return true;
- if (borderColor != 0)
- return true;
- if (!string.IsNullOrEmpty(resImage))
- return true;
- if (!string.IsNullOrEmpty(resSprite))
- return true;
- if (resImageZoom != null)
- return true;
- if (!string.IsNullOrEmpty(link))
- return true;
- if (drawable != null)
- return true;
- return false;
- }
- public void Combine(TextAttribute other, bool isCover = true)
- {
- if (other.fontColor != 0)
- {
- this.fontColor = other.fontColor;
- }
- if (other.fontSize != 0)
- {
- this.fontSize = other.fontSize;
- }
- if (!string.IsNullOrEmpty(other.fontName))
- {
- this.fontName = other.fontName;
- }
- if (other.fontStyle != 0)
- {
- this.fontStyle = other.fontStyle;
- }
- if (other.anchor != RichTextAlignment.taNA)
- {
- this.anchor = other.anchor;
- }
- if (other.borderCount > 0)
- {
- this.borderCount = other.borderCount;
- }
- if (other.borderColor != 0)
- {
- this.borderColor = other.borderColor;
- }
- if (!string.IsNullOrEmpty(other.resImage))
- {
- this.resImage = other.resImage;
- }
- if (!string.IsNullOrEmpty(other.resSprite))
- {
- this.resSprite = other.resSprite;
- }
- if (other.resImageZoom != null)
- {
- this.resImageZoom = CUtils.TryClone(other.resImageZoom);
- }
- if (other.drawable != null)
- {
- this.drawable = CUtils.TryClone(other.drawable);
- }
- if (isCover && !string.IsNullOrEmpty(other.link))
- {
- this.link = other.link;
- }
- else if (!isCover)
- {
- this.link += other.link;
- }
- }
- public static TextAttribute Combine(TextAttribute src, TextAttribute dst)
- {
- TextAttribute ret = new TextAttribute(src);
- ret.Combine(dst);
- return ret;
- }
- }
- //------------------------------------------------------------------------------------------------------------------------
- //------------------------------------------------------------------------------------------------------------------------
- public class ImageZoomParser : CommonLang.Parser.ParserAdapter
- {
- public ImageZoomParser() : base(typeof(ImageZoom)) { }
- public override object StringToObject(string text)
- {
- return ImageZoom.FromString(text);
- }
- public override string ObjectToString(object obj)
- {
- return ImageZoom.ToString(obj as ImageZoom);
- }
- }
- public class ImageZoom : ICloneable
- {
- static ImageZoom()
- {
- Parser.RegistParser(new ImageZoomParser());
- }
- public enum ImageFill
- {
- Clamp,
- Repeat,
- }
- public ImageFill Filling = ImageFill.Clamp;
- public float Width;
- public float Height;
- public object Clone()
- {
- ImageZoom ret = new ImageZoom();
- ret.Filling = this.Filling;
- ret.Width = this.Width;
- ret.Height = this.Height;
- return ret;
- }
- public static bool Equals(ImageZoom a, ImageZoom b)
- {
- if (a != null && b != null)
- {
- if (a.Filling != b.Filling)
- return false;
- if (a.Width != b.Width)
- return false;
- if (a.Height != b.Height)
- return false;
- return true;
- }
- return a == b;
- }
- public override string ToString()
- {
- return ToString(this);
- }
- public static ImageZoom FromString(string text)
- {
- string[] kvs = text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- if (kvs.Length >= 2)
- {
- ImageZoom ret = new ImageZoom();
- ret.Width = float.Parse(kvs[0]);
- ret.Height = float.Parse(kvs[1]);
- if (kvs.Length >= 3)
- {
- ret.Filling = (ImageFill)Enum.Parse(typeof(ImageFill), kvs[2], true);
- }
- return ret;
- }
- return null;
- }
- public static string ToString(ImageZoom obj)
- {
- if (obj != null)
- {
- return string.Format("{0},{1},{2}", obj.Width, obj.Height, obj.Filling);
- }
- return null;
- }
- }
- //------------------------------------------------------------------------------------------------------------------------
- /////////////////////////////////////////////////////////////////////////////////////////////
- //
- /////////////////////////////////////////////////////////////////////////////////////////////
- /// <summary>
- /// 含有属性的文字
- /// </summary>
- public class AttributedString : ICloneable
- {
- private string text = "";
- private List<TextAttribute> attributes = new List<TextAttribute>();
- public AttributedString()
- {
- }
- public AttributedString(string other, TextAttribute ta)
- {
- Append(other, ta);
- }
- public object Clone()
- {
- AttributedString ret = new AttributedString();
- ret.text = this.text;
- ret.attributes = CUtils.CloneList<TextAttribute>(this.attributes);
- return ret;
- }
- public override bool Equals(object obj)
- {
- if (obj is AttributedString)
- {
- AttributedString other = obj as AttributedString;
- if (other.text.Equals(this.text))
- {
- for (int i = text.Length - 1; i >= 0; --i)
- {
- if (!other.attributes[i].Equals(this.attributes[i]))
- {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- public bool SetAttribute(int index, int len, TextAttribute ta)
- {
- if (index + len <= attributes.Count)
- {
- int end = index + len;
- for (int i = index; i < end; ++i)
- {
- attributes[i] = ta;
- }
- return true;
- }
- return false;
- }
- public AttributedString AddAttribute(TextAttribute attribute, bool isCover = true)
- {
- return AddAttribute(attribute, 0, text.Length, isCover);
- }
- public AttributedString AddAttribute(TextAttribute attribute, int beginIndex, int count, bool isCover = true)
- {
- int endIndex = beginIndex + count;
- for (int i = beginIndex; i < endIndex; ++i)
- {
- attributes[i].Combine(attribute, isCover);
- }
- return this;
- }
- public AttributedString Append(AttributedString other)
- {
- if (other != null && !string.IsNullOrEmpty(other.text))
- {
- text += other.text;
- for (int i = 0; i < other.text.Length; ++i)
- {
- attributes.Add(other.attributes[i]);
- }
- }
- return this;
- }
- public AttributedString Append(string other)
- {
- if (attributes.Count > 0)
- {
- TextAttribute lastAttr = attributes[attributes.Count - 1];
- Append(other, lastAttr);
- }
- else
- {
- Append(other, new TextAttribute(Color.COLOR_WHITE, 12));
- }
- return this;
- }
- public AttributedString Append(string other, TextAttribute ta)
- {
- if (!string.IsNullOrEmpty(other))
- {
- text += other;
- for (int i = 0; i < other.Length; ++i)
- {
- attributes.Add(ta);
- }
- }
- return this;
- }
- public AttributedString DeleteString(int beginIndex, int count)
- {
- text = text.Remove(beginIndex, count);
- attributes.RemoveRange(beginIndex, count);
- return this;
- }
- public AttributedString ClearString()
- {
- text = "";
- attributes.Clear();
- return this;
- }
- public int Length
- {
- get
- {
- return text.Length;
- }
- }
- override public string ToString()
- {
- return text;
- }
- public char GetChar(int index)
- {
- if (index < text.Length)
- {
- return text[index];
- }
- return default(char);
- }
- public TextAttribute GetAttribute(int index)
- {
- if (index < attributes.Count)
- {
- return attributes[index];
- }
- return null;
- }
- }
- //------------------------------------------------------------------------------------------------------------------------
- //------------------------------------------------------------------------------------------------------------------------
- public class AttributedStringDecoder
- {
- protected Logger log = LoggerFactory.GetLogger("AttributedStringDecoder");
- public const string TEXT_XML_KEY_COLOR = "color";
- public const string TEXT_XML_KEY_SIZE = "size";
- public const string TEXT_XML_KEY_FACE = "face";
- public const string TEXT_XML_KEY_STYLE = "style";
- public const string TEXT_XML_KEY_B_COUNT = "border";
- public const string TEXT_XML_KEY_B_COLOR = "bcolor";
- public const string TEXT_XML_KEY_RES_IMG = "img";
- /// <summary>
- /// @"宽,高"
- /// img_zoom = "width,height"
- /// </summary>
- public const string TEXT_XML_KEY_RES_IMAGE_ZOOM = "img_zoom";
- /// <summary>
- /// @"资源名,精灵名,动画ID"
- /// spr = "res/sprite.xml,sprite_name,anim"
- /// </summary>
- public const string TEXT_XML_KEY_RES_SPR = "spr";
- public const string TEXT_XML_KEY_LINK = "link";
- public const string TEXT_XML_KEY_LINE_ANCHOR = "anchor";
- public const string TEXT_XML_NODE_BREAK = "br";
- public const string TEXT_XML_NODE_SPACE = "p";
- public virtual AttributedString CreateFromXML(XmlDocument xml, TextAttribute defaultTA = null)
- {
- AttributedString attr = new AttributedString();
- TextAttribute curAttr = (defaultTA != null) ? defaultTA : new TextAttribute(Color.COLOR_WHITE, 16);
- try
- {
- internalBuildXML(attr, xml.DocumentElement, curAttr);
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- }
- return attr;
- }
- public virtual AttributedString CreateFromXML(string text, TextAttribute defaultTA = null)
- {
- XmlDocument xml = XmlUtil.FromString(text);
- return CreateFromXML(xml, defaultTA);
- }
- protected virtual void DecodeAttribute(XmlElement node, XmlAttribute x_attr, TextAttribute attr)
- {
- switch (x_attr.Name)
- {
- case TEXT_XML_KEY_COLOR:
- {
- string kv = node.GetAttribute(TEXT_XML_KEY_COLOR);
- uint argb = uint.Parse(kv, System.Globalization.NumberStyles.HexNumber);
- attr.fontColor = Color.toRGBA(argb);
- }
- break;
- case TEXT_XML_KEY_SIZE:
- {
- attr.fontSize = int.Parse(node.GetAttribute(TEXT_XML_KEY_SIZE));
- }
- break;
- case TEXT_XML_KEY_STYLE:
- {
- string style = node.GetAttribute(TEXT_XML_KEY_STYLE);
- int value;
- if (int.TryParse(style, out value))
- {
- attr.fontStyle = (FontStyle)value;
- }
- else
- {
- attr.fontStyle = (FontStyle) Enum.Parse(typeof(FontStyle), style);
- }
- }
- break;
- case TEXT_XML_KEY_FACE:
- {
- attr.fontName = node.GetAttribute(TEXT_XML_KEY_FACE);
- }
- break;
- case TEXT_XML_KEY_B_COUNT:
- {
- attr.borderCount = (Data.TextBorderCount)int.Parse(node.GetAttribute(TEXT_XML_KEY_B_COUNT));
- }
- break;
- case TEXT_XML_KEY_B_COLOR:
- {
- string kv = node.GetAttribute(TEXT_XML_KEY_B_COLOR);
- uint argb = uint.Parse(kv, System.Globalization.NumberStyles.HexNumber);
- attr.borderColor = Color.toRGBA(argb);
- }
- break;
- case TEXT_XML_KEY_RES_IMG:
- {
- attr.resImage = node.GetAttribute(TEXT_XML_KEY_RES_IMG);
- }
- break;
- case TEXT_XML_KEY_RES_SPR:
- {
- attr.resSprite = node.GetAttribute(TEXT_XML_KEY_RES_SPR);
- }
- break;
- case TEXT_XML_KEY_RES_IMAGE_ZOOM:
- {
- attr.resImageZoom = ImageZoom.FromString(node.GetAttribute(TEXT_XML_KEY_RES_IMAGE_ZOOM));
- }
- break;
- case TEXT_XML_KEY_LINK:
- {
- attr.link = node.GetAttribute(TEXT_XML_KEY_LINK);
- }
- break;
- case TEXT_XML_KEY_LINE_ANCHOR:
- {
- string value = node.GetAttribute(TEXT_XML_KEY_LINE_ANCHOR);
- try
- {
- attr.anchor = (RichTextAlignment)Enum.Parse(typeof(RichTextAlignment), value, true);
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- }
- }
- break;
- }
- TextDrawable drawable = ITextDrawableFactory.Instance.CreateTextDrawable(x_attr.Name, x_attr.Value);
- if (drawable != null)
- {
- attr.drawable = drawable;
- }
- }
- private void internalBuildXML(AttributedString atext, XmlElement node, TextAttribute parentAttr)
- {
- string nname = node.Name;
- TextAttribute attr = new TextAttribute();
- foreach (XmlAttribute x_attr in node.Attributes)
- {
- DecodeAttribute(node, x_attr, attr);
- }
- attr = TextAttribute.Combine(parentAttr, attr);
- if (!attr.IsValid())
- {
- attr = parentAttr;
- }
- if (node.ChildNodes.Count > 0)
- {
- foreach (XmlNode e in node.ChildNodes)
- {
- if (e is XmlText || e is XmlCDataSection)
- {
- atext.Append(e.Value, attr);
- }
- else if (e is XmlElement)
- {
- internalBuildXML(atext, e as XmlElement, attr);
- }
- }
- }
- if (string.Equals(nname, TEXT_XML_NODE_BREAK))
- {
- atext.Append("\n", attr);
- }
- else if (string.Equals(nname, TEXT_XML_NODE_SPACE))
- {
- atext.Append(" ", attr);
- }
- }
- }
- }
|